gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Move to private copy constrcutors
0 2 0
default
2 files changed with 201 insertions and 148 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
... ...
@@ -197,557 +197,572 @@
197 197

	
198 198
    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
    bool isOct(char c) {
204 204
      return '0' <= c && c <='7'; 
205 205
    }
206 206
    
207 207
    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
    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
    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
    bool isIdentifierFirstChar(char c) {
226 226
      return ('a' <= c && c <= 'z') ||
227 227
	('A' <= c && c <= 'Z') || c == '_';
228 228
    }
229 229

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

	
235 235
    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
    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
  template <typename Digraph>
390
  class DigraphReader;
391

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

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

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

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

	
442 454
    typedef _Digraph Digraph;
443 455
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
444 456
    
445 457
  private:
446 458

	
447 459

	
448 460
    std::istream* _is;
449 461
    bool local_is;
450 462

	
451 463
    Digraph& _digraph;
452 464

	
453 465
    std::string _nodes_caption;
454 466
    std::string _arcs_caption;
455 467
    std::string _attributes_caption;
456 468

	
457 469
    typedef std::map<std::string, Node> NodeIndex;
458 470
    NodeIndex _node_index;
459 471
    typedef std::map<std::string, Arc> ArcIndex;
460 472
    ArcIndex _arc_index;
461 473
    
462 474
    typedef std::vector<std::pair<std::string, 
463 475
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
464 476
    NodeMaps _node_maps; 
465 477

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

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

	
474 486
    bool _use_nodes;
475 487
    bool _use_arcs;
476 488

	
477 489
    bool _skip_nodes;
478 490
    bool _skip_arcs;
479 491

	
480 492
    int line_num;
481 493
    std::istringstream line;
482 494

	
483 495
  public:
484 496

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

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

	
512
    /// \brief Copy constructor
513
    ///
514
    /// The copy constructor transfers all data from the other reader,
515
    /// therefore the copied reader will not be usable more. 
516
    DigraphReader(DigraphReader& other) 
517
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
518
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
519
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
520

	
521
      other._is = 0;
522
      other.local_is = false;
523
      
524
      _node_index.swap(other._node_index);
525
      _arc_index.swap(other._arc_index);
526

	
527
      _node_maps.swap(other._node_maps);
528
      _arc_maps.swap(other._arc_maps);
529
      _attributes.swap(other._attributes);
530

	
531
      _nodes_caption = other._nodes_caption;
532
      _arcs_caption = other._arcs_caption;
533
      _attributes_caption = other._attributes_caption;
534

	
535
    }
536

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

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

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

	
554 541
      if (local_is) {
555 542
	delete _is;
556 543
      }
557 544

	
558 545
    }
559 546

	
560 547
  private:
561
    
548

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

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

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

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

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

	
575
    }
576

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

	
564 579
  public:
565 580

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

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

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

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

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

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

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

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

	
669 684
    /// @}
670 685

	
671 686
    /// \name Select section by name
672 687
    /// @{
673 688

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

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

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

	
698 713
    /// @}
699 714

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

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

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

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

	
752 767
    /// \brief Use previously constructed arc set
753 768
    ///
... ...
@@ -993,512 +1008,524 @@
993 1008

	
994 1009
          typename NodeIndex::iterator it;
995 1010
 
996 1011
          it = _node_index.find(source_token);
997 1012
          if (it == _node_index.end()) {
998 1013
            std::ostringstream msg;
999 1014
            msg << "Item not found: " << source_token;
1000 1015
            throw DataFormatError(msg.str().c_str());
1001 1016
          }
1002 1017
          Node source = it->second;
1003 1018

	
1004 1019
          it = _node_index.find(target_token);
1005 1020
          if (it == _node_index.end()) {       
1006 1021
            std::ostringstream msg;            
1007 1022
            msg << "Item not found: " << target_token;
1008 1023
            throw DataFormatError(msg.str().c_str());
1009 1024
          }                                          
1010 1025
          Node target = it->second;                            
1011 1026

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

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

	
1032 1047
      }
1033 1048
      if (readSuccess()) {
1034 1049
	line.putback(c);
1035 1050
      }
1036 1051
    }
1037 1052

	
1038 1053
    void readAttributes() {
1039 1054

	
1040 1055
      std::set<std::string> read_attr;
1041 1056

	
1042 1057
      char c;
1043 1058
      while (readLine() && line >> c && c != '@') {
1044 1059
	line.putback(c);
1045 1060
	
1046 1061
	std::string attr, token;
1047 1062
	if (!_reader_bits::readToken(line, attr))
1048 1063
	  throw DataFormatError("Attribute name not found");
1049 1064
	if (!_reader_bits::readToken(line, token))
1050 1065
	  throw DataFormatError("Attribute value not found");
1051 1066
	if (line >> c)
1052 1067
	  throw DataFormatError("Extra character on the end of line");	  
1053 1068

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

	
1072 1087
      }
1073 1088
      if (readSuccess()) {
1074 1089
	line.putback(c);
1075 1090
      }
1076 1091
      for (typename Attributes::iterator it = _attributes.begin();
1077 1092
	   it != _attributes.end(); ++it) {
1078 1093
	if (read_attr.find(it->first) == read_attr.end()) {
1079 1094
	  std::ostringstream msg;
1080 1095
	  msg << "Attribute not found in file: " << it->first;
1081 1096
	  throw DataFormatError(msg.str().c_str());
1082 1097
	}	
1083 1098
      }
1084 1099
    }
1085 1100

	
1086 1101
  public:
1087 1102

	
1088 1103
    /// \name Execution of the reader    
1089 1104
    /// @{
1090 1105

	
1091 1106
    /// \brief Start the batch processing
1092 1107
    ///
1093 1108
    /// This function starts the batch processing
1094 1109
    void run() {
1095 1110
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1096 1111
      if (!*_is) {
1097 1112
	throw DataFormatError("Cannot find file");
1098 1113
      }
1099 1114
      
1100 1115
      bool nodes_done = _skip_nodes;
1101 1116
      bool arcs_done = _skip_arcs;
1102 1117
      bool attributes_done = false;
1103 1118

	
1104 1119
      line_num = 0;      
1105 1120
      readLine();
1106 1121
      skipSection();
1107 1122

	
1108 1123
      while (readSuccess()) {
1109 1124
	try {
1110 1125
	  char c;
1111 1126
	  std::string section, caption;
1112 1127
	  line >> c;
1113 1128
	  _reader_bits::readToken(line, section);
1114 1129
	  _reader_bits::readToken(line, caption);
1115 1130

	
1116 1131
	  if (line >> c) 
1117 1132
	    throw DataFormatError("Extra character on the end of line");
1118 1133

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

	
1145 1160
      if (!nodes_done) {
1146 1161
	throw DataFormatError("Section @nodes not found");
1147 1162
      }
1148 1163

	
1149 1164
      if (!arcs_done) {
1150 1165
	throw DataFormatError("Section @arcs not found");
1151 1166
      }
1152 1167

	
1153 1168
      if (!attributes_done && !_attributes.empty()) {
1154 1169
	throw DataFormatError("Section @attributes not found");
1155 1170
      }
1156 1171

	
1157 1172
    }
1158 1173

	
1159 1174
    /// @}
1160 1175
    
1161 1176
  };
1162 1177

	
1163 1178
  /// \relates DigraphReader
1164 1179
  template <typename Digraph>
1165 1180
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1166 1181
    DigraphReader<Digraph> tmp(is, digraph);
1167 1182
    return tmp;
1168 1183
  }
1169 1184

	
1170 1185
  /// \relates DigraphReader
1171 1186
  template <typename Digraph>
1172 1187
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
1173 1188
				       Digraph& digraph) {
1174 1189
    DigraphReader<Digraph> tmp(fn, digraph);
1175 1190
    return tmp;
1176 1191
  }
1177 1192

	
1178 1193
  /// \relates DigraphReader
1179 1194
  template <typename Digraph>
1180 1195
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1181 1196
    DigraphReader<Digraph> tmp(fn, digraph);
1182 1197
    return tmp;
1183 1198
  }
1184 1199

	
1200
  template <typename Graph>
1201
  class GraphReader;
1202

	
1203
  template <typename Graph>
1204
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph);    
1205

	
1206
  template <typename Graph>
1207
  GraphReader<Graph> graphReader(const std::string& fn, Graph& graph);   
1208

	
1209
  template <typename Graph>
1210
  GraphReader<Graph> graphReader(const char *fn, Graph& graph);    
1211

	
1185 1212
  /// \ingroup lemon_io
1186 1213
  ///  
1187 1214
  /// \brief LGF reader for undirected graphs
1188 1215
  ///
1189 1216
  /// This utility reads an \ref lgf-format "LGF" file.
1190 1217
  template <typename _Graph>
1191 1218
  class GraphReader {
1192 1219
  public:
1193 1220

	
1194 1221
    typedef _Graph Graph;
1195 1222
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1196 1223
    
1197 1224
  private:
1198 1225

	
1199 1226
    std::istream* _is;
1200 1227
    bool local_is;
1201 1228

	
1202 1229
    Graph& _graph;
1203 1230

	
1204 1231
    std::string _nodes_caption;
1205 1232
    std::string _edges_caption;
1206 1233
    std::string _attributes_caption;
1207 1234

	
1208 1235
    typedef std::map<std::string, Node> NodeIndex;
1209 1236
    NodeIndex _node_index;
1210 1237
    typedef std::map<std::string, Edge> EdgeIndex;
1211 1238
    EdgeIndex _edge_index;
1212 1239
    
1213 1240
    typedef std::vector<std::pair<std::string, 
1214 1241
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1215 1242
    NodeMaps _node_maps; 
1216 1243

	
1217 1244
    typedef std::vector<std::pair<std::string,
1218 1245
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1219 1246
    EdgeMaps _edge_maps;
1220 1247

	
1221 1248
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1222 1249
      Attributes;
1223 1250
    Attributes _attributes;
1224 1251

	
1225 1252
    bool _use_nodes;
1226 1253
    bool _use_edges;
1227 1254

	
1228 1255
    bool _skip_nodes;
1229 1256
    bool _skip_edges;
1230 1257

	
1231 1258
    int line_num;
1232 1259
    std::istringstream line;
1233 1260

	
1234 1261
  public:
1235 1262

	
1236 1263
    /// \brief Constructor
1237 1264
    ///
1238 1265
    /// Construct a undirected graph reader, which reads from the given
1239 1266
    /// input stream.
1240 1267
    GraphReader(std::istream& is, Graph& graph) 
1241 1268
      : _is(&is), local_is(false), _graph(graph),
1242 1269
	_use_nodes(false), _use_edges(false),
1243 1270
	_skip_nodes(false), _skip_edges(false) {}
1244 1271

	
1245 1272
    /// \brief Constructor
1246 1273
    ///
1247 1274
    /// Construct a undirected graph reader, which reads from the given
1248 1275
    /// file.
1249 1276
    GraphReader(const std::string& fn, Graph& graph) 
1250 1277
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1251 1278
    	_use_nodes(false), _use_edges(false),
1252 1279
	_skip_nodes(false), _skip_edges(false) {}
1253 1280
    
1254 1281
    /// \brief Constructor
1255 1282
    ///
1256 1283
    /// Construct a undirected graph reader, which reads from the given
1257 1284
    /// file.
1258 1285
    GraphReader(const char* fn, Graph& graph) 
1259 1286
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1260 1287
    	_use_nodes(false), _use_edges(false),
1261 1288
	_skip_nodes(false), _skip_edges(false) {}
1262 1289

	
1263
    /// \brief Copy constructor
1264
    ///
1265
    /// The copy constructor transfers all data from the other reader,
1266
    /// therefore the copied reader will not be usable more. 
1267
    GraphReader(GraphReader& other) 
1268
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1269
	_use_nodes(other._use_nodes), _use_edges(other._use_edges),
1270
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1271

	
1272
      other._is = 0;
1273
      other.local_is = false;
1274
      
1275
      _node_index.swap(other._node_index);
1276
      _edge_index.swap(other._edge_index);
1277

	
1278
      _node_maps.swap(other._node_maps);
1279
      _edge_maps.swap(other._edge_maps);
1280
      _attributes.swap(other._attributes);
1281

	
1282
      _nodes_caption = other._nodes_caption;
1283
      _edges_caption = other._edges_caption;
1284
      _attributes_caption = other._attributes_caption;
1285

	
1286
    }
1287

	
1288 1290
    /// \brief Destructor
1289 1291
    ~GraphReader() {
1290 1292
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1291 1293
	   it != _node_maps.end(); ++it) {
1292 1294
	delete it->second;
1293 1295
      }
1294 1296

	
1295 1297
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1296 1298
	   it != _edge_maps.end(); ++it) {
1297 1299
	delete it->second;
1298 1300
      }
1299 1301

	
1300 1302
      for (typename Attributes::iterator it = _attributes.begin(); 
1301 1303
	   it != _attributes.end(); ++it) {
1302 1304
	delete it->second;
1303 1305
      }
1304 1306

	
1305 1307
      if (local_is) {
1306 1308
	delete _is;
1307 1309
      }
1308 1310

	
1309 1311
    }
1310 1312

	
1311 1313
  private:
1312
    
1314
    friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph);    
1315
    friend GraphReader<Graph> graphReader<>(const std::string& fn, 
1316
					    Graph& graph);   
1317
    friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph);    
1318

	
1319
    GraphReader(GraphReader& other) 
1320
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1321
	_use_nodes(other._use_nodes), _use_edges(other._use_edges),
1322
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1323

	
1324
      other._is = 0;
1325
      other.local_is = false;
1326
      
1327
      _node_index.swap(other._node_index);
1328
      _edge_index.swap(other._edge_index);
1329

	
1330
      _node_maps.swap(other._node_maps);
1331
      _edge_maps.swap(other._edge_maps);
1332
      _attributes.swap(other._attributes);
1333

	
1334
      _nodes_caption = other._nodes_caption;
1335
      _edges_caption = other._edges_caption;
1336
      _attributes_caption = other._attributes_caption;
1337

	
1338
    }
1339

	
1313 1340
    GraphReader& operator=(const GraphReader&);
1314 1341

	
1315 1342
  public:
1316 1343

	
1317 1344
    /// \name Reading rules
1318 1345
    /// @{
1319 1346
    
1320 1347
    /// \brief Node map reading rule
1321 1348
    ///
1322 1349
    /// Add a node map reading rule to the reader.
1323 1350
    template <typename Map>
1324 1351
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1325 1352
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1326 1353
      _reader_bits::MapStorageBase<Node>* storage = 
1327 1354
	new _reader_bits::MapStorage<Node, Map>(map);
1328 1355
      _node_maps.push_back(std::make_pair(caption, storage));
1329 1356
      return *this;
1330 1357
    }
1331 1358

	
1332 1359
    /// \brief Node map reading rule
1333 1360
    ///
1334 1361
    /// Add a node map reading rule with specialized converter to the
1335 1362
    /// reader.
1336 1363
    template <typename Map, typename Converter>
1337 1364
    GraphReader& nodeMap(const std::string& caption, Map& map, 
1338 1365
			   const Converter& converter = Converter()) {
1339 1366
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1340 1367
      _reader_bits::MapStorageBase<Node>* storage = 
1341 1368
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1342 1369
      _node_maps.push_back(std::make_pair(caption, storage));
1343 1370
      return *this;
1344 1371
    }
1345 1372

	
1346 1373
    /// \brief Edge map reading rule
1347 1374
    ///
1348 1375
    /// Add an edge map reading rule to the reader.
1349 1376
    template <typename Map>
1350 1377
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1351 1378
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1352 1379
      _reader_bits::MapStorageBase<Edge>* storage = 
1353 1380
	new _reader_bits::MapStorage<Edge, Map>(map);
1354 1381
      _edge_maps.push_back(std::make_pair(caption, storage));
1355 1382
      return *this;
1356 1383
    }
1357 1384

	
1358 1385
    /// \brief Edge map reading rule
1359 1386
    ///
1360 1387
    /// Add an edge map reading rule with specialized converter to the
1361 1388
    /// reader.
1362 1389
    template <typename Map, typename Converter>
1363 1390
    GraphReader& edgeMap(const std::string& caption, Map& map, 
1364 1391
			  const Converter& converter = Converter()) {
1365 1392
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1366 1393
      _reader_bits::MapStorageBase<Edge>* storage = 
1367 1394
	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1368 1395
      _edge_maps.push_back(std::make_pair(caption, storage));
1369 1396
      return *this;
1370 1397
    }
1371 1398

	
1372 1399
    /// \brief Arc map reading rule
1373 1400
    ///
1374 1401
    /// Add an arc map reading rule to the reader.
1375 1402
    template <typename Map>
1376 1403
    GraphReader& arcMap(const std::string& caption, Map& map) {
1377 1404
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1378 1405
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1379 1406
	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1380 1407
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1381 1408
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1382 1409
	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1383 1410
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1384 1411
      return *this;
1385 1412
    }
1386 1413

	
1387 1414
    /// \brief Arc map reading rule
1388 1415
    ///
1389 1416
    /// Add an arc map reading rule with specialized converter to the
1390 1417
    /// reader.
1391 1418
    template <typename Map, typename Converter>
1392 1419
    GraphReader& arcMap(const std::string& caption, Map& map, 
1393 1420
			  const Converter& converter = Converter()) {
1394 1421
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1395 1422
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1396 1423
	new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1397 1424
	(_graph, map, converter);
1398 1425
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1399 1426
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1400 1427
	new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1401 1428
	(_graph, map, converter);
1402 1429
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1403 1430
      return *this;
1404 1431
    }
1405 1432

	
1406 1433
    /// \brief Attribute reading rule
1407 1434
    ///
1408 1435
    /// Add an attribute reading rule to the reader.
1409 1436
    template <typename Value>
1410 1437
    GraphReader& attribute(const std::string& caption, Value& value) {
1411 1438
      _reader_bits::ValueStorageBase* storage = 
1412 1439
	new _reader_bits::ValueStorage<Value>(value);
1413 1440
      _attributes.insert(std::make_pair(caption, storage));
1414 1441
      return *this;
1415 1442
    }
1416 1443

	
1417 1444
    /// \brief Attribute reading rule
1418 1445
    ///
1419 1446
    /// Add an attribute reading rule with specialized converter to the
1420 1447
    /// reader.
1421 1448
    template <typename Value, typename Converter>
1422 1449
    GraphReader& attribute(const std::string& caption, Value& value, 
1423 1450
			     const Converter& converter = Converter()) {
1424 1451
      _reader_bits::ValueStorageBase* storage = 
1425 1452
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1426 1453
      _attributes.insert(std::make_pair(caption, storage));
1427 1454
      return *this;
1428 1455
    }
1429 1456

	
1430 1457
    /// \brief Node reading rule
1431 1458
    ///
1432 1459
    /// Add a node reading rule to reader.
1433 1460
    GraphReader& node(const std::string& caption, Node& node) {
1434 1461
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1435 1462
      Converter converter(_node_index);
1436 1463
      _reader_bits::ValueStorageBase* storage = 
1437 1464
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1438 1465
      _attributes.insert(std::make_pair(caption, storage));
1439 1466
      return *this;
1440 1467
    }
1441 1468

	
1442 1469
    /// \brief Edge reading rule
1443 1470
    ///
1444 1471
    /// Add an edge reading rule to reader.
1445 1472
    GraphReader& edge(const std::string& caption, Edge& edge) {
1446 1473
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1447 1474
      Converter converter(_edge_index);
1448 1475
      _reader_bits::ValueStorageBase* storage = 
1449 1476
	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1450 1477
      _attributes.insert(std::make_pair(caption, storage));
1451 1478
      return *this;
1452 1479
    }
1453 1480

	
1454 1481
    /// \brief Arc reading rule
1455 1482
    ///
1456 1483
    /// Add an arc reading rule to reader.
1457 1484
    GraphReader& arc(const std::string& caption, Arc& arc) {
1458 1485
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1459 1486
      Converter converter(_graph, _edge_index);
1460 1487
      _reader_bits::ValueStorageBase* storage = 
1461 1488
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1462 1489
      _attributes.insert(std::make_pair(caption, storage));
1463 1490
      return *this;
1464 1491
    }
1465 1492

	
1466 1493
    /// @}
1467 1494

	
1468 1495
    /// \name Select section by name
1469 1496
    /// @{
1470 1497

	
1471 1498
    /// \brief Set \c \@nodes section to be read
1472 1499
    ///
1473 1500
    /// Set \c \@nodes section to be read
1474 1501
    GraphReader& nodes(const std::string& caption) {
1475 1502
      _nodes_caption = caption;
1476 1503
      return *this;
1477 1504
    }
1478 1505

	
1479 1506
    /// \brief Set \c \@edges section to be read
1480 1507
    ///
1481 1508
    /// Set \c \@edges section to be read
1482 1509
    GraphReader& edges(const std::string& caption) {
1483 1510
      _edges_caption = caption;
1484 1511
      return *this;
1485 1512
    }
1486 1513

	
1487 1514
    /// \brief Set \c \@attributes section to be read
1488 1515
    ///
1489 1516
    /// Set \c \@attributes section to be read
1490 1517
    GraphReader& attributes(const std::string& caption) {
1491 1518
      _attributes_caption = caption;
1492 1519
      return *this;
1493 1520
    }
1494 1521

	
1495 1522
    /// @}
1496 1523

	
1497 1524
    /// \name Using previously constructed node or edge set
1498 1525
    /// @{
1499 1526

	
1500 1527
    /// \brief Use previously constructed node set
1501 1528
    ///
1502 1529
    /// Use previously constructed node set, and specify the node
1503 1530
    /// label map.
1504 1531
    template <typename Map>
... ...
@@ -1788,730 +1815,721 @@
1788 1815
	Edge e;
1789 1816
	if (!_use_edges) {
1790 1817

	
1791 1818
          typename NodeIndex::iterator it;
1792 1819
 
1793 1820
          it = _node_index.find(source_token);
1794 1821
          if (it == _node_index.end()) {
1795 1822
            std::ostringstream msg;
1796 1823
            msg << "Item not found: " << source_token;
1797 1824
            throw DataFormatError(msg.str().c_str());
1798 1825
          }
1799 1826
          Node source = it->second;
1800 1827

	
1801 1828
          it = _node_index.find(target_token);
1802 1829
          if (it == _node_index.end()) {       
1803 1830
            std::ostringstream msg;            
1804 1831
            msg << "Item not found: " << target_token;
1805 1832
            throw DataFormatError(msg.str().c_str());
1806 1833
          }                                          
1807 1834
          Node target = it->second;                            
1808 1835

	
1809 1836
	  e = _graph.addEdge(source, target);
1810 1837
	  if (label_index != -1) 
1811 1838
	    _edge_index.insert(std::make_pair(tokens[label_index], e));
1812 1839
	} else {
1813 1840
	  if (label_index == -1) 
1814 1841
	    throw DataFormatError("Label map not found in file");
1815 1842
	  typename std::map<std::string, Edge>::iterator it =
1816 1843
	    _edge_index.find(tokens[label_index]);
1817 1844
	  if (it == _edge_index.end()) {
1818 1845
	    std::ostringstream msg;
1819 1846
	    msg << "Edge with label not found: " << tokens[label_index];
1820 1847
	    throw DataFormatError(msg.str().c_str());	    
1821 1848
	  }
1822 1849
	  e = it->second;
1823 1850
	}
1824 1851

	
1825 1852
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1826 1853
	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
1827 1854
	}
1828 1855

	
1829 1856
      }
1830 1857
      if (readSuccess()) {
1831 1858
	line.putback(c);
1832 1859
      }
1833 1860
    }
1834 1861

	
1835 1862
    void readAttributes() {
1836 1863

	
1837 1864
      std::set<std::string> read_attr;
1838 1865

	
1839 1866
      char c;
1840 1867
      while (readLine() && line >> c && c != '@') {
1841 1868
	line.putback(c);
1842 1869
	
1843 1870
	std::string attr, token;
1844 1871
	if (!_reader_bits::readToken(line, attr))
1845 1872
	  throw DataFormatError("Attribute name not found");
1846 1873
	if (!_reader_bits::readToken(line, token))
1847 1874
	  throw DataFormatError("Attribute value not found");
1848 1875
	if (line >> c)
1849 1876
	  throw DataFormatError("Extra character on the end of line");	  
1850 1877

	
1851 1878
	{
1852 1879
	  std::set<std::string>::iterator it = read_attr.find(attr);
1853 1880
	  if (it != read_attr.end()) {
1854 1881
	    std::ostringstream msg;
1855 1882
	    msg << "Multiple occurence of attribute " << attr;
1856 1883
	    throw DataFormatError(msg.str().c_str());
1857 1884
	  }
1858 1885
	  read_attr.insert(attr);
1859 1886
	}
1860 1887
	
1861 1888
	{
1862 1889
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1863 1890
	  while (it != _attributes.end() && it->first == attr) {
1864 1891
	    it->second->set(token);
1865 1892
	    ++it;
1866 1893
	  }
1867 1894
	}
1868 1895

	
1869 1896
      }
1870 1897
      if (readSuccess()) {
1871 1898
	line.putback(c);
1872 1899
      }
1873 1900
      for (typename Attributes::iterator it = _attributes.begin();
1874 1901
	   it != _attributes.end(); ++it) {
1875 1902
	if (read_attr.find(it->first) == read_attr.end()) {
1876 1903
	  std::ostringstream msg;
1877 1904
	  msg << "Attribute not found in file: " << it->first;
1878 1905
	  throw DataFormatError(msg.str().c_str());
1879 1906
	}	
1880 1907
      }
1881 1908
    }
1882 1909

	
1883 1910
  public:
1884 1911

	
1885 1912
    /// \name Execution of the reader    
1886 1913
    /// @{
1887 1914

	
1888 1915
    /// \brief Start the batch processing
1889 1916
    ///
1890 1917
    /// This function starts the batch processing
1891 1918
    void run() {
1892 1919
      
1893 1920
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1894 1921
      
1895 1922
      bool nodes_done = _skip_nodes;
1896 1923
      bool edges_done = _skip_edges;
1897 1924
      bool attributes_done = false;
1898 1925

	
1899 1926
      line_num = 0;      
1900 1927
      readLine();
1901 1928
      skipSection();
1902 1929

	
1903 1930
      while (readSuccess()) {
1904 1931
	try {
1905 1932
	  char c;
1906 1933
	  std::string section, caption;
1907 1934
	  line >> c;
1908 1935
	  _reader_bits::readToken(line, section);
1909 1936
	  _reader_bits::readToken(line, caption);
1910 1937

	
1911 1938
	  if (line >> c) 
1912 1939
	    throw DataFormatError("Extra character on the end of line");
1913 1940

	
1914 1941
	  if (section == "nodes" && !nodes_done) {
1915 1942
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1916 1943
	      readNodes();
1917 1944
	      nodes_done = true;
1918 1945
	    }
1919 1946
	  } else if ((section == "edges" || section == "arcs") && 
1920 1947
		     !edges_done) {
1921 1948
	    if (_edges_caption.empty() || _edges_caption == caption) {
1922 1949
	      readEdges();
1923 1950
	      edges_done = true;
1924 1951
	    }
1925 1952
	  } else if (section == "attributes" && !attributes_done) {
1926 1953
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1927 1954
	      readAttributes();
1928 1955
	      attributes_done = true;
1929 1956
	    }
1930 1957
	  } else {
1931 1958
	    readLine();
1932 1959
	    skipSection();
1933 1960
	  }
1934 1961
	} catch (DataFormatError& error) {
1935 1962
	  error.line(line_num);
1936 1963
	  throw;
1937 1964
	}	
1938 1965
      }
1939 1966

	
1940 1967
      if (!nodes_done) {
1941 1968
	throw DataFormatError("Section @nodes not found");
1942 1969
      }
1943 1970

	
1944 1971
      if (!edges_done) {
1945 1972
	throw DataFormatError("Section @edges not found");
1946 1973
      }
1947 1974

	
1948 1975
      if (!attributes_done && !_attributes.empty()) {
1949 1976
	throw DataFormatError("Section @attributes not found");
1950 1977
      }
1951 1978

	
1952 1979
    }
1953 1980

	
1954 1981
    /// @}
1955 1982
    
1956 1983
  };
1957 1984

	
1958 1985
  /// \relates GraphReader
1959 1986
  template <typename Graph>
1960 1987
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
1961 1988
    GraphReader<Graph> tmp(is, graph);
1962 1989
    return tmp;
1963 1990
  }
1964 1991

	
1965 1992
  /// \relates GraphReader
1966 1993
  template <typename Graph>
1967 1994
  GraphReader<Graph> graphReader(const std::string& fn, 
1968 1995
				       Graph& graph) {
1969 1996
    GraphReader<Graph> tmp(fn, graph);
1970 1997
    return tmp;
1971 1998
  }
1972 1999

	
1973 2000
  /// \relates GraphReader
1974 2001
  template <typename Graph>
1975 2002
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
1976 2003
    GraphReader<Graph> tmp(fn, graph);
1977 2004
    return tmp;
1978 2005
  }
1979 2006

	
2007
  class SectionReader;
2008

	
2009
  SectionReader sectionReader(std::istream& is);
2010
  SectionReader sectionReader(const std::string& fn);
2011
  SectionReader sectionReader(const char* fn);
2012
  
1980 2013
  /// \brief Section reader class
1981 2014
  ///
1982 2015
  /// In the \e LGF file extra sections can be placed, which contain
1983 2016
  /// any data in arbitrary format. Such sections can be read with
1984 2017
  /// this class. A reading rule can be added with two different
1985 2018
  /// functions, with the \c sectionLines() function a functor can
1986 2019
  /// process the section line-by-line. While with the \c
1987 2020
  /// sectionStream() member the section can be read from an input
1988 2021
  /// stream.
1989 2022
  class SectionReader {
1990 2023
  private:
1991 2024
    
1992 2025
    std::istream* _is;
1993 2026
    bool local_is;
1994 2027

	
1995 2028
    typedef std::map<std::string, _reader_bits::Section*> Sections;
1996 2029
    Sections _sections;
1997 2030

	
1998 2031
    int line_num;
1999 2032
    std::istringstream line;
2000 2033

	
2001 2034
  public:
2002 2035

	
2003 2036
    /// \brief Constructor
2004 2037
    ///
2005 2038
    /// Construct a section reader, which reads from the given input
2006 2039
    /// stream.
2007 2040
    SectionReader(std::istream& is) 
2008 2041
      : _is(&is), local_is(false) {}
2009 2042

	
2010 2043
    /// \brief Constructor
2011 2044
    ///
2012 2045
    /// Construct a section reader, which reads from the given file.
2013 2046
    SectionReader(const std::string& fn) 
2014 2047
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2015 2048
    
2016 2049
    /// \brief Constructor
2017 2050
    ///
2018 2051
    /// Construct a section reader, which reads from the given file.
2019 2052
    SectionReader(const char* fn) 
2020 2053
      : _is(new std::ifstream(fn)), local_is(true) {}
2021 2054

	
2022
    /// \brief Copy constructor
2023
    ///
2024
    /// The copy constructor transfers all data from the other reader,
2025
    /// therefore the copied reader will not be usable more. 
2026
    SectionReader(SectionReader& other) 
2027
      : _is(other._is), local_is(other.local_is) {
2028

	
2029
      other._is = 0;
2030
      other.local_is = false;
2031
      
2032
      _sections.swap(other._sections);
2033
    }
2034

	
2035 2055
    /// \brief Destructor
2036 2056
    ~SectionReader() {
2037 2057
      for (Sections::iterator it = _sections.begin(); 
2038 2058
	   it != _sections.end(); ++it) {
2039 2059
	delete it->second;
2040 2060
      }
2041 2061

	
2042 2062
      if (local_is) {
2043 2063
	delete _is;
2044 2064
      }
2045 2065

	
2046 2066
    }
2047 2067

	
2048 2068
  private:
2069

	
2070
    friend SectionReader sectionReader(std::istream& is);
2071
    friend SectionReader sectionReader(const std::string& fn);
2072
    friend SectionReader sectionReader(const char* fn);
2073

	
2074
    SectionReader(SectionReader& other) 
2075
      : _is(other._is), local_is(other.local_is) {
2076

	
2077
      other._is = 0;
2078
      other.local_is = false;
2079
      
2080
      _sections.swap(other._sections);
2081
    }
2049 2082
    
2050 2083
    SectionReader& operator=(const SectionReader&);
2051 2084

	
2052 2085
  public:
2053 2086

	
2054 2087
    /// \name Section readers
2055 2088
    /// @{
2056 2089

	
2057 2090
    /// \brief Add a section processor with line oriented reading
2058 2091
    ///
2059 2092
    /// The first parameter is the type descriptor of the section, the
2060 2093
    /// second is a functor, which takes just one \c std::string
2061 2094
    /// parameter. At the reading process, each line of the section
2062 2095
    /// will be given to the functor object. However, the empty lines
2063 2096
    /// and the comment lines are filtered out, and the leading
2064 2097
    /// whitespaces are trimmed from each processed string.
2065 2098
    ///
2066 2099
    /// For example let's see a section, which contain several
2067 2100
    /// integers, which should be inserted into a vector.
2068 2101
    ///\code
2069 2102
    ///  @numbers
2070 2103
    ///  12 45 23
2071 2104
    ///  4
2072 2105
    ///  23 6
2073 2106
    ///\endcode
2074 2107
    ///
2075 2108
    /// The functor is implemented as an struct:
2076 2109
    ///\code
2077 2110
    ///  struct NumberSection {
2078 2111
    ///    std::vector<int>& _data;
2079 2112
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2080 2113
    ///    void operator()(const std::string& line) {
2081 2114
    ///      std::istringstream ls(line);
2082 2115
    ///      int value;
2083 2116
    ///      while (ls >> value) _data.push_back(value);
2084 2117
    ///    }
2085 2118
    ///  };
2086 2119
    ///
2087 2120
    ///  // ...
2088 2121
    ///
2089 2122
    ///  reader.sectionLines("numbers", NumberSection(vec));  
2090 2123
    ///\endcode
2091 2124
    template <typename Functor>
2092 2125
    SectionReader& sectionLines(const std::string& type, Functor functor) {
2093 2126
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
2094 2127
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2095 2128
		   "Multiple reading of section.");
2096 2129
      _sections.insert(std::make_pair(type, 
2097 2130
        new _reader_bits::LineSection<Functor>(functor)));
2098 2131
      return *this;
2099 2132
    }
2100 2133

	
2101 2134

	
2102 2135
    /// \brief Add a section processor with stream oriented reading
2103 2136
    ///
2104 2137
    /// The first parameter is the type of the section, the second is
2105 2138
    /// a functor, which takes an \c std::istream& and an int&
2106 2139
    /// parameter, the latter regard to the line number of stream. The
2107 2140
    /// functor can read the input while the section go on, and the
2108 2141
    /// line number should be modified accordingly.
2109 2142
    template <typename Functor>
2110 2143
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2111 2144
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
2112 2145
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2113 2146
		   "Multiple reading of section.");
2114 2147
      _sections.insert(std::make_pair(type, 
2115 2148
	 new _reader_bits::StreamSection<Functor>(functor)));
2116 2149
      return *this;
2117 2150
    }    
2118 2151
    
2119 2152
    /// @}
2120 2153

	
2121 2154
  private:
2122 2155

	
2123 2156
    bool readLine() {
2124 2157
      std::string str;
2125 2158
      while(++line_num, std::getline(*_is, str)) {
2126 2159
	line.clear(); line.str(str);
2127 2160
	char c;
2128 2161
	if (line >> std::ws >> c && c != '#') {
2129 2162
	  line.putback(c);
2130 2163
	  return true;
2131 2164
	}
2132 2165
      }
2133 2166
      return false;
2134 2167
    }
2135 2168

	
2136 2169
    bool readSuccess() {
2137 2170
      return static_cast<bool>(*_is);
2138 2171
    }
2139 2172
    
2140 2173
    void skipSection() {
2141 2174
      char c;
2142 2175
      while (readSuccess() && line >> c && c != '@') {
2143 2176
	readLine();
2144 2177
      }
2145 2178
      line.putback(c);
2146 2179
    }
2147 2180

	
2148 2181
  public:
2149 2182

	
2150 2183

	
2151 2184
    /// \name Execution of the reader    
2152 2185
    /// @{
2153 2186

	
2154 2187
    /// \brief Start the batch processing
2155 2188
    ///
2156 2189
    /// This function starts the batch processing
2157 2190
    void run() {
2158 2191
      
2159 2192
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2160 2193
      
2161 2194
      std::set<std::string> extra_sections;
2162 2195

	
2163 2196
      line_num = 0;      
2164 2197
      readLine();
2165 2198
      skipSection();
2166 2199

	
2167 2200
      while (readSuccess()) {
2168 2201
	try {
2169 2202
	  char c;
2170 2203
	  std::string section, caption;
2171 2204
	  line >> c;
2172 2205
	  _reader_bits::readToken(line, section);
2173 2206
	  _reader_bits::readToken(line, caption);
2174 2207

	
2175 2208
	  if (line >> c) 
2176 2209
	    throw DataFormatError("Extra character on the end of line");
2177 2210

	
2178 2211
	  if (extra_sections.find(section) != extra_sections.end()) {
2179 2212
	    std::ostringstream msg;
2180 2213
	    msg << "Multiple occurence of section " << section;
2181 2214
	    throw DataFormatError(msg.str().c_str());
2182 2215
	  }
2183 2216
	  Sections::iterator it = _sections.find(section);
2184 2217
	  if (it != _sections.end()) {
2185 2218
	    extra_sections.insert(section);
2186 2219
	    it->second->process(*_is, line_num);
2187 2220
	  }
2188 2221
	  readLine();
2189 2222
	  skipSection();
2190 2223
	} catch (DataFormatError& error) {
2191 2224
	  error.line(line_num);
2192 2225
	  throw;
2193 2226
	}	
2194 2227
      }
2195 2228
      for (Sections::iterator it = _sections.begin();
2196 2229
	   it != _sections.end(); ++it) {
2197 2230
	if (extra_sections.find(it->first) == extra_sections.end()) {
2198 2231
	  std::ostringstream os;
2199 2232
	  os << "Cannot find section: " << it->first;
2200 2233
	  throw DataFormatError(os.str().c_str());
2201 2234
	}
2202 2235
      }
2203 2236
    }
2204 2237

	
2205 2238
    /// @}
2206 2239
        
2207 2240
  };
2208 2241

	
2209 2242
  /// \relates SectionReader
2210 2243
  inline SectionReader sectionReader(std::istream& is) {
2211 2244
    SectionReader tmp(is);
2212 2245
    return tmp;
2213 2246
  }
2214 2247

	
2215 2248
  /// \relates SectionReader
2216 2249
  inline SectionReader sectionReader(const std::string& fn) {
2217 2250
    SectionReader tmp(fn);
2218 2251
    return tmp;
2219 2252
  }
2220 2253

	
2221 2254
  /// \relates SectionReader
2222 2255
  inline SectionReader sectionReader(const char* fn) {
2223 2256
    SectionReader tmp(fn);
2224 2257
    return tmp;
2225 2258
  }
2226 2259

	
2227 2260
  /// \ingroup lemon_io
2228 2261
  ///
2229 2262
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
2230 2263
  ///
2231 2264
  /// This class can be used to read the sections, the map names and
2232 2265
  /// the attributes from a file. Usually, the Lemon programs know
2233 2266
  /// that, which type of graph, which maps and which attributes
2234 2267
  /// should be read from a file, but in general tools (like glemon)
2235 2268
  /// the contents of an LGF file should be guessed somehow. This class
2236 2269
  /// reads the graph and stores the appropriate information for
2237 2270
  /// reading the graph.
2238 2271
  ///
2239 2272
  ///\code LgfContents contents("graph.lgf"); 
2240 2273
  /// contents.run();
2241 2274
  ///
2242 2275
  /// // does it contain any node section and arc section
2243 2276
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2244 2277
  ///   std::cerr << "Failure, cannot find graph" << std::endl;
2245 2278
  ///   return -1;
2246 2279
  /// }
2247 2280
  /// std::cout << "The name of the default node section : " 
2248 2281
  ///           << contents.nodeSection(0) << std::endl;
2249 2282
  /// std::cout << "The number of the arc maps : " 
2250 2283
  ///           << contents.arcMaps(0).size() << std::endl;
2251 2284
  /// std::cout << "The name of second arc map : " 
2252 2285
  ///           << contents.arcMaps(0)[1] << std::endl;
2253 2286
  ///\endcode
2254 2287
  class LgfContents {    
2255 2288
  private:
2256 2289

	
2257 2290
    std::istream* _is;
2258 2291
    bool local_is;
2259 2292

	
2260 2293
    std::vector<std::string> _node_sections;
2261 2294
    std::vector<std::string> _edge_sections;
2262 2295
    std::vector<std::string> _attribute_sections;
2263 2296
    std::vector<std::string> _extra_sections;
2264 2297

	
2265 2298
    std::vector<bool> _arc_sections;
2266 2299

	
2267 2300
    std::vector<std::vector<std::string> > _node_maps;
2268 2301
    std::vector<std::vector<std::string> > _edge_maps;
2269 2302

	
2270 2303
    std::vector<std::vector<std::string> > _attributes;
2271 2304

	
2272 2305

	
2273 2306
    int line_num;
2274 2307
    std::istringstream line;
2275 2308
    
2276 2309
  public:
2277 2310

	
2278 2311
    /// \brief Constructor
2279 2312
    ///
2280 2313
    /// Construct an \e LGF contents reader, which reads from the given
2281 2314
    /// input stream.
2282 2315
    LgfContents(std::istream& is) 
2283 2316
      : _is(&is), local_is(false) {}
2284 2317

	
2285 2318
    /// \brief Constructor
2286 2319
    ///
2287 2320
    /// Construct an \e LGF contents reader, which reads from the given
2288 2321
    /// file.
2289 2322
    LgfContents(const std::string& fn) 
2290 2323
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2291 2324

	
2292 2325
    /// \brief Constructor
2293 2326
    ///
2294 2327
    /// Construct an \e LGF contents reader, which reads from the given
2295 2328
    /// file.
2296 2329
    LgfContents(const char* fn)
2297 2330
      : _is(new std::ifstream(fn)), local_is(true) {}
2298

	
2299
    /// \brief Copy constructor
2300
    ///
2301
    /// The copy constructor transfers all data from the other reader,
2302
    /// therefore the copied reader will not be usable more. 
2303
    LgfContents(LgfContents& other)
2304
      : _is(other._is), local_is(other.local_is) {
2305
      
2306
      other._is = 0;
2307
      other.local_is = false;
2308
      
2309
      _node_sections.swap(other._node_sections);
2310
      _edge_sections.swap(other._edge_sections);
2311
      _attribute_sections.swap(other._attribute_sections);
2312
      _extra_sections.swap(other._extra_sections);
2313

	
2314
      _arc_sections.swap(other._arc_sections);
2315

	
2316
      _node_maps.swap(other._node_maps);
2317
      _edge_maps.swap(other._edge_maps);
2318
      _attributes.swap(other._attributes);
2319
    }
2320 2331
    
2321 2332
    /// \brief Destructor
2322 2333
    ~LgfContents() {
2323 2334
      if (local_is) delete _is;
2324 2335
    }
2325 2336

	
2337
  private:
2338
    
2339
    LgfContents(const LgfContents&);
2340
    LgfContents& operator=(const LgfContents&);
2341

	
2342
  public:
2343

	
2326 2344

	
2327 2345
    /// \name Node sections
2328 2346
    /// @{
2329 2347

	
2330 2348
    /// \brief Gives back the number of node sections in the file.
2331 2349
    ///
2332 2350
    /// Gives back the number of node sections in the file.
2333 2351
    int nodeSectionNum() const {
2334 2352
      return _node_sections.size();
2335 2353
    }
2336 2354

	
2337 2355
    /// \brief Returns the section name at the given position. 
2338 2356
    ///
2339 2357
    /// Returns the section name at the given position. 
2340 2358
    const std::string& nodeSection(int i) const {
2341 2359
      return _node_sections[i];
2342 2360
    }
2343 2361

	
2344 2362
    /// \brief Gives back the node maps for the given section.
2345 2363
    ///
2346 2364
    /// Gives back the node maps for the given section.
2347 2365
    const std::vector<std::string>& nodeMapNames(int i) const {
2348 2366
      return _node_maps[i];
2349 2367
    }
2350 2368

	
2351 2369
    /// @}
2352 2370

	
2353 2371
    /// \name Arc/Edge sections 
2354 2372
    /// @{
2355 2373

	
2356 2374
    /// \brief Gives back the number of arc/edge sections in the file.
2357 2375
    ///
2358 2376
    /// Gives back the number of arc/edge sections in the file.
2359 2377
    /// \note It is synonym of \c edgeSectionNum().
2360 2378
    int arcSectionNum() const {
2361 2379
      return _edge_sections.size();
2362 2380
    }
2363 2381

	
2364 2382
    /// \brief Returns the section name at the given position. 
2365 2383
    ///
2366 2384
    /// Returns the section name at the given position. 
2367 2385
    /// \note It is synonym of \c edgeSection().
2368 2386
    const std::string& arcSection(int i) const {
2369 2387
      return _edge_sections[i];
2370 2388
    }
2371 2389

	
2372 2390
    /// \brief Gives back the arc/edge maps for the given section.
2373 2391
    ///
2374 2392
    /// Gives back the arc/edge maps for the given section.
2375 2393
    /// \note It is synonym of \c edgeMapNames().
2376 2394
    const std::vector<std::string>& arcMapNames(int i) const {
2377 2395
      return _edge_maps[i];
2378 2396
    }
2379 2397

	
2380 2398
    /// @}
2381 2399

	
2382 2400
    /// \name Synonyms
2383 2401
    /// @{
2384 2402

	
2385 2403
    /// \brief Gives back the number of arc/edge sections in the file.
2386 2404
    ///
2387 2405
    /// Gives back the number of arc/edge sections in the file.
2388 2406
    /// \note It is synonym of \c arcSectionNum().
2389 2407
    int edgeSectionNum() const {
2390 2408
      return _edge_sections.size();
2391 2409
    }
2392 2410

	
2393 2411
    /// \brief Returns the section name at the given position. 
2394 2412
    ///
2395 2413
    /// Returns the section name at the given position. 
2396 2414
    /// \note It is synonym of \c arcSection().
2397 2415
    const std::string& edgeSection(int i) const {
2398 2416
      return _edge_sections[i];
2399 2417
    }
2400 2418

	
2401 2419
    /// \brief Gives back the edge maps for the given section.
2402 2420
    ///
2403 2421
    /// Gives back the edge maps for the given section.
2404 2422
    /// \note It is synonym of \c arcMapNames().
2405 2423
    const std::vector<std::string>& edgeMapNames(int i) const {
2406 2424
      return _edge_maps[i];
2407 2425
    }
2408 2426

	
2409 2427
    /// @}
2410 2428

	
2411 2429
    /// \name Attribute sections   
2412 2430
    /// @{
2413 2431

	
2414 2432
    /// \brief Gives back the number of attribute sections in the file.
2415 2433
    ///
2416 2434
    /// Gives back the number of attribute sections in the file.
2417 2435
    int attributeSectionNum() const {
2418 2436
      return _attribute_sections.size();
2419 2437
    }
2420 2438

	
2421 2439
    /// \brief Returns the section name at the given position. 
2422 2440
    ///
2423 2441
    /// Returns the section name at the given position. 
2424 2442
    const std::string& attributeSectionNames(int i) const {
2425 2443
      return _attribute_sections[i];
2426 2444
    }
2427 2445

	
2428 2446
    /// \brief Gives back the attributes for the given section.
2429 2447
    ///
2430 2448
    /// Gives back the attributes for the given section.
2431 2449
    const std::vector<std::string>& attributes(int i) const {
2432 2450
      return _attributes[i];
2433 2451
    }
2434 2452

	
2435 2453
    /// @}
2436 2454

	
2437 2455
    /// \name Extra sections   
2438 2456
    /// @{
2439 2457

	
2440 2458
    /// \brief Gives back the number of extra sections in the file.
2441 2459
    ///
2442 2460
    /// Gives back the number of extra sections in the file.
2443 2461
    int extraSectionNum() const {
2444 2462
      return _extra_sections.size();
2445 2463
    }
2446 2464

	
2447 2465
    /// \brief Returns the extra section type at the given position. 
2448 2466
    ///
2449 2467
    /// Returns the section type at the given position. 
2450 2468
    const std::string& extraSection(int i) const {
2451 2469
      return _extra_sections[i];
2452 2470
    }
2453 2471

	
2454 2472
    /// @}
2455 2473

	
2456 2474
  private:
2457 2475

	
2458 2476
    bool readLine() {
2459 2477
      std::string str;
2460 2478
      while(++line_num, std::getline(*_is, str)) {
2461 2479
	line.clear(); line.str(str);
2462 2480
	char c;
2463 2481
	if (line >> std::ws >> c && c != '#') {
2464 2482
	  line.putback(c);
2465 2483
	  return true;
2466 2484
	}
2467 2485
      }
2468 2486
      return false;
2469 2487
    }
2470 2488

	
2471 2489
    bool readSuccess() {
2472 2490
      return static_cast<bool>(*_is);
2473 2491
    }
2474 2492

	
2475 2493
    void skipSection() {
2476 2494
      char c;
2477 2495
      while (readSuccess() && line >> c && c != '@') {
2478 2496
	readLine();
2479 2497
      }
2480 2498
      line.putback(c);
2481 2499
    }
2482 2500

	
2483 2501
    void readMaps(std::vector<std::string>& maps) {
2484 2502
      char c;
2485 2503
      if (!readLine() || !(line >> c) || c == '@') {
2486 2504
	if (readSuccess() && line) line.putback(c);
2487 2505
	return;
2488 2506
      }
2489 2507
      line.putback(c);
2490 2508
      std::string map;
2491 2509
      while (_reader_bits::readToken(line, map)) {
2492 2510
	maps.push_back(map);
2493 2511
      }
2494 2512
    }
2495 2513

	
2496 2514
    void readAttributes(std::vector<std::string>& attrs) {
2497 2515
      readLine();
2498 2516
      char c;
2499 2517
      while (readSuccess() && line >> c && c != '@') {
2500 2518
	line.putback(c);
2501 2519
	std::string attr;
2502 2520
	_reader_bits::readToken(line, attr);
2503 2521
	attrs.push_back(attr);
2504 2522
	readLine();
2505 2523
      }
2506 2524
      line.putback(c);
2507 2525
    }
2508 2526

	
2509 2527
  public:
2510 2528

	
2511 2529
    /// \name Execution of the contents reader    
2512 2530
    /// @{
2513 2531

	
2514 2532
    /// \brief Start the reading
2515 2533
    ///
2516 2534
    /// This function starts the reading
2517 2535
    void run() {
Ignore white space 384 line context
... ...
@@ -115,1061 +115,1096 @@
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
    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
    bool isEscaped(char c) {
234 234
      return c == '\\' || c == '\"' || c == '\'' || 
235 235
	c == '\a' || c == '\b';
236 236
    }
237 237

	
238 238
    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
    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
    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

	
308
  template <typename Digraph>
309
  class DigraphWriter;
310

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

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

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

	
356 371
    typedef _Digraph Digraph;
357 372
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
358 373
    
359 374
  private:
360 375

	
361 376

	
362 377
    std::ostream* _os;
363 378
    bool local_os;
364 379

	
365
    Digraph& _digraph;
380
    const Digraph& _digraph;
366 381

	
367 382
    std::string _nodes_caption;
368 383
    std::string _arcs_caption;
369 384
    std::string _attributes_caption;
370 385
    
371 386
    typedef std::map<Node, std::string> NodeIndex;
372 387
    NodeIndex _node_index;
373 388
    typedef std::map<Arc, std::string> ArcIndex;
374 389
    ArcIndex _arc_index;
375 390

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

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

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

	
388 403
    bool _skip_nodes;
389 404
    bool _skip_arcs;
390 405

	
391 406
  public:
392 407

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

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

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

	
417
    /// \brief Copy constructor
418
    ///
419
    /// The copy constructor transfers all data from the other writer,
420
    /// therefore the copied writer will not be usable more. 
421
    DigraphWriter(DigraphWriter& other) 
422
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
423
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
424

	
425
      other._os = 0;
426
      other.local_os = false;
427

	
428
      _node_index.swap(other._node_index);
429
      _arc_index.swap(other._arc_index);
430

	
431
      _node_maps.swap(other._node_maps);
432
      _arc_maps.swap(other._arc_maps);
433
      _attributes.swap(other._attributes);
434

	
435
      _nodes_caption = other._nodes_caption;
436
      _arcs_caption = other._arcs_caption;
437
      _attributes_caption = other._attributes_caption;
438
    }
439

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

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

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

	
457 449
      if (local_os) {
458 450
	delete _os;
459 451
      }
460 452
    }
461 453

	
462 454
  private:
455

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

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

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

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

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

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

	
466 484
  public:
467 485

	
468 486
    /// \name Writing rules
469 487
    /// @{
470 488
    
471 489
    /// \brief Node map reading rule
472 490
    ///
473 491
    /// Add a node map reading rule to the writer.
474 492
    template <typename Map>
475 493
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
476 494
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
477 495
      _writer_bits::MapStorageBase<Node>* storage = 
478 496
	new _writer_bits::MapStorage<Node, Map>(map);
479 497
      _node_maps.push_back(std::make_pair(caption, storage));
480 498
      return *this;
481 499
    }
482 500

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

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

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

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

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

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

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

	
571 589
    /// \name Select section by name
572 590
    /// @{
573 591

	
574 592
    /// \brief Set \c \@nodes section to be read
575 593
    ///
576 594
    /// Set \c \@nodes section to be read
577 595
    DigraphWriter& nodes(const std::string& caption) {
578 596
      _nodes_caption = caption;
579 597
      return *this;
580 598
    }
581 599

	
582 600
    /// \brief Set \c \@arcs section to be read
583 601
    ///
584 602
    /// Set \c \@arcs section to be read
585 603
    DigraphWriter& arcs(const std::string& caption) {
586 604
      _arcs_caption = caption;
587 605
      return *this;
588 606
    }
589 607

	
590 608
    /// \brief Set \c \@attributes section to be read
591 609
    ///
592 610
    /// Set \c \@attributes section to be read
593 611
    DigraphWriter& attributes(const std::string& caption) {
594 612
      _attributes_caption = caption;
595 613
      return *this;
596 614
    }
597 615

	
598 616
    /// \name Skipping section
599 617
    /// @{
600 618

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

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

	
619 637
    /// @}
620 638

	
621 639
  private:
622 640

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

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

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

	
648 666
      std::vector<Node> nodes;
649 667
      for (NodeIt n(_digraph); n != INVALID; ++n) {
650 668
	nodes.push_back(n);
651 669
      }
652 670
      
653 671
      if (label == 0) {
654 672
	IdMap<Digraph, Node> id_map(_digraph);
655 673
	_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
656 674
	std::sort(nodes.begin(), nodes.end(), id_less);
657 675
      } else {
658 676
	label->sort(nodes);
659 677
      }
660 678

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

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

	
693 711
      if (label == 0) {
694 712
	for (NodeIt n(_digraph); n != INVALID; ++n) {
695 713
	  std::ostringstream os;
696 714
	  os << _digraph.id(n);
697 715
	  _node_index.insert(std::make_pair(n, os.str()));	  
698 716
	}	
699 717
      } else {
700 718
	for (NodeIt n(_digraph); n != INVALID; ++n) {
701 719
	  std::string value = label->get(n);	  
702 720
	  _node_index.insert(std::make_pair(n, value));
703 721
	}
704 722
      }
705 723
    }
706 724

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

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

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

	
733 751
      std::vector<Arc> arcs;
734 752
      for (ArcIt n(_digraph); n != INVALID; ++n) {
735 753
	arcs.push_back(n);
736 754
      }
737 755
      
738 756
      if (label == 0) {
739 757
	IdMap<Digraph, Arc> id_map(_digraph);
740 758
	_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
741 759
	std::sort(arcs.begin(), arcs.end(), id_less);
742 760
      } else {
743 761
	label->sort(arcs);
744 762
      }
745 763

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

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

	
784 802
      if (label == 0) {
785 803
	for (ArcIt a(_digraph); a != INVALID; ++a) {
786 804
	  std::ostringstream os;
787 805
	  os << _digraph.id(a);
788 806
	  _arc_index.insert(std::make_pair(a, os.str()));	  
789 807
	}	
790 808
      } else {
791 809
	for (ArcIt a(_digraph); a != INVALID; ++a) {
792 810
	  std::string value = label->get(a);	  
793 811
	  _arc_index.insert(std::make_pair(a, value));
794 812
	}
795 813
      }
796 814
    }
797 815

	
798 816
    void writeAttributes() {
799 817
      if (_attributes.empty()) return;
800 818
      *_os << "@attributes";
801 819
      if (!_attributes_caption.empty()) {
802 820
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
803 821
      }
804 822
      *_os << std::endl;
805 823
      for (typename Attributes::iterator it = _attributes.begin();
806 824
	   it != _attributes.end(); ++it) {
807 825
	_writer_bits::writeToken(*_os, it->first) << ' ';
808 826
	_writer_bits::writeToken(*_os, it->second->get());
809 827
	*_os << std::endl;
810 828
      }
811 829
    }
812 830
    
813 831
  public:
814 832
    
815 833
    /// \name Execution of the writer    
816 834
    /// @{
817 835

	
818 836
    /// \brief Start the batch processing
819 837
    ///
820 838
    /// This function starts the batch processing
821 839
    void run() {
822 840
      if (!_skip_nodes) {
823 841
	writeNodes();
824 842
      } else {
825 843
	createNodeIndex();
826 844
      }
827 845
      if (!_skip_arcs) {      
828 846
	writeArcs();
829 847
      } else {
830 848
	createArcIndex();
831 849
      }
832 850
      writeAttributes();
833 851
    }
834 852

	
835 853
    /// \brief Gives back the stream of the writer
836 854
    ///
837 855
    /// Gives back the stream of the writer
838 856
    std::ostream& ostream() {
839 857
      return *_os;
840 858
    }
841 859

	
842 860
    /// @}
843 861
  };
844 862

	
845 863
  /// \relates DigraphWriter
846 864
  template <typename Digraph>
847
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, Digraph& digraph) {
865
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, 
866
				       const Digraph& digraph) {
848 867
    DigraphWriter<Digraph> tmp(os, digraph);
849 868
    return tmp;
850 869
  }
851 870

	
852 871
  /// \relates DigraphWriter
853 872
  template <typename Digraph>
854 873
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
855
				       Digraph& digraph) {
874
				       const Digraph& digraph) {
856 875
    DigraphWriter<Digraph> tmp(fn, digraph);
857 876
    return tmp;
858 877
  }
859 878

	
860 879
  /// \relates DigraphWriter
861 880
  template <typename Digraph>
862
  DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
881
  DigraphWriter<Digraph> digraphWriter(const char* fn, 
882
				       const Digraph& digraph) {
863 883
    DigraphWriter<Digraph> tmp(fn, digraph);
864 884
    return tmp;
865 885
  }
866 886

	
887
  template <typename Graph>
888
  class GraphWriter;
889

	
890
  template <typename Graph>
891
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph);    
892

	
893
  template <typename Graph>
894
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph);   
895

	
896
  template <typename Graph>
897
  GraphWriter<Graph> graphWriter(const char *fn, const Graph& graph);    
898

	
867 899
  /// \ingroup lemon_io
868 900
  ///  
869 901
  /// \brief LGF writer for directed graphs
870 902
  ///
871 903
  /// This utility writes an \ref lgf-format "LGF" file.
872 904
  template <typename _Graph>
873 905
  class GraphWriter {
874 906
  public:
875 907

	
876 908
    typedef _Graph Graph;
877 909
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
878 910
    
879 911
  private:
880 912

	
881 913

	
882 914
    std::ostream* _os;
883 915
    bool local_os;
884 916

	
885 917
    Graph& _graph;
886 918

	
887 919
    std::string _nodes_caption;
888 920
    std::string _edges_caption;
889 921
    std::string _attributes_caption;
890 922
    
891 923
    typedef std::map<Node, std::string> NodeIndex;
892 924
    NodeIndex _node_index;
893 925
    typedef std::map<Edge, std::string> EdgeIndex;
894 926
    EdgeIndex _edge_index;
895 927

	
896 928
    typedef std::vector<std::pair<std::string, 
897 929
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
898 930
    NodeMaps _node_maps; 
899 931

	
900 932
    typedef std::vector<std::pair<std::string, 
901 933
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
902 934
    EdgeMaps _edge_maps;
903 935

	
904 936
    typedef std::vector<std::pair<std::string, 
905 937
      _writer_bits::ValueStorageBase*> > Attributes;
906 938
    Attributes _attributes;
907 939

	
908 940
    bool _skip_nodes;
909 941
    bool _skip_edges;
910 942

	
911 943
  public:
912 944

	
913 945
    /// \brief Constructor
914 946
    ///
915 947
    /// Construct a directed graph writer, which writes to the given
916 948
    /// output stream.
917
    GraphWriter(std::ostream& is, Graph& graph) 
949
    GraphWriter(std::ostream& is, const Graph& graph) 
918 950
      : _os(&is), local_os(false), _graph(graph),
919 951
	_skip_nodes(false), _skip_edges(false) {}
920 952

	
921 953
    /// \brief Constructor
922 954
    ///
923 955
    /// Construct a directed graph writer, which writes to the given
924 956
    /// output file.
925
    GraphWriter(const std::string& fn, Graph& graph) 
957
    GraphWriter(const std::string& fn, const Graph& graph) 
926 958
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
927 959
	_skip_nodes(false), _skip_edges(false) {}
928 960

	
929 961
    /// \brief Constructor
930 962
    ///
931 963
    /// Construct a directed graph writer, which writes to the given
932 964
    /// output file.
933
    GraphWriter(const char* fn, Graph& graph) 
965
    GraphWriter(const char* fn, const Graph& graph) 
934 966
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
935 967
	_skip_nodes(false), _skip_edges(false) {}
936 968

	
937
    /// \brief Copy constructor
938
    ///
939
    /// The copy constructor transfers all data from the other writer,
940
    /// therefore the copied writer will not be usable more. 
941
    GraphWriter(GraphWriter& other) 
942
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
943
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
944

	
945
      other._os = 0;
946
      other.local_os = false;
947

	
948
      _node_index.swap(other._node_index);
949
      _edge_index.swap(other._edge_index);
950

	
951
      _node_maps.swap(other._node_maps);
952
      _edge_maps.swap(other._edge_maps);
953
      _attributes.swap(other._attributes);
954

	
955
      _nodes_caption = other._nodes_caption;
956
      _edges_caption = other._edges_caption;
957
      _attributes_caption = other._attributes_caption;
958
    }
959

	
960 969
    /// \brief Destructor
961 970
    ~GraphWriter() {
962 971
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
963 972
	   it != _node_maps.end(); ++it) {
964 973
	delete it->second;
965 974
      }
966 975

	
967 976
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
968 977
	   it != _edge_maps.end(); ++it) {
969 978
	delete it->second;
970 979
      }
971 980

	
972 981
      for (typename Attributes::iterator it = _attributes.begin(); 
973 982
	   it != _attributes.end(); ++it) {
974 983
	delete it->second;
975 984
      }
976 985

	
977 986
      if (local_os) {
978 987
	delete _os;
979 988
      }
980 989
    }
990
    
991
  private:
981 992

	
982
  private:
983
    
993
    friend GraphWriter<Graph> graphWriter<>(std::ostream& os, 
994
					    const Graph& graph);    
995
    friend GraphWriter<Graph> graphWriter<>(const std::string& fn, 
996
					    const Graph& graph);   
997
    friend GraphWriter<Graph> graphWriter<>(const char *fn, 
998
					    const Graph& graph);    
999

	
1000
    GraphWriter(GraphWriter& other) 
1001
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1002
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1003

	
1004
      other._os = 0;
1005
      other.local_os = false;
1006

	
1007
      _node_index.swap(other._node_index);
1008
      _edge_index.swap(other._edge_index);
1009

	
1010
      _node_maps.swap(other._node_maps);
1011
      _edge_maps.swap(other._edge_maps);
1012
      _attributes.swap(other._attributes);
1013

	
1014
      _nodes_caption = other._nodes_caption;
1015
      _edges_caption = other._edges_caption;
1016
      _attributes_caption = other._attributes_caption;
1017
    }
1018

	
984 1019
    GraphWriter& operator=(const GraphWriter&);
985 1020

	
986 1021
  public:
987 1022

	
988 1023
    /// \name Writing rules
989 1024
    /// @{
990 1025
    
991 1026
    /// \brief Node map reading rule
992 1027
    ///
993 1028
    /// Add a node map reading rule to the writer.
994 1029
    template <typename Map>
995 1030
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
996 1031
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
997 1032
      _writer_bits::MapStorageBase<Node>* storage = 
998 1033
	new _writer_bits::MapStorage<Node, Map>(map);
999 1034
      _node_maps.push_back(std::make_pair(caption, storage));
1000 1035
      return *this;
1001 1036
    }
1002 1037

	
1003 1038
    /// \brief Node map writing rule
1004 1039
    ///
1005 1040
    /// Add a node map writing rule with specialized converter to the
1006 1041
    /// writer.
1007 1042
    template <typename Map, typename Converter>
1008 1043
    GraphWriter& nodeMap(const std::string& caption, const Map& map, 
1009 1044
			   const Converter& converter = Converter()) {
1010 1045
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1011 1046
      _writer_bits::MapStorageBase<Node>* storage = 
1012 1047
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1013 1048
      _node_maps.push_back(std::make_pair(caption, storage));
1014 1049
      return *this;
1015 1050
    }
1016 1051

	
1017 1052
    /// \brief Edge map writing rule
1018 1053
    ///
1019 1054
    /// Add an edge map writing rule to the writer.
1020 1055
    template <typename Map>
1021 1056
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1022 1057
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1023 1058
      _writer_bits::MapStorageBase<Edge>* storage = 
1024 1059
	new _writer_bits::MapStorage<Edge, Map>(map);
1025 1060
      _edge_maps.push_back(std::make_pair(caption, storage));
1026 1061
      return *this;
1027 1062
    }
1028 1063

	
1029 1064
    /// \brief Edge map writing rule
1030 1065
    ///
1031 1066
    /// Add an edge map writing rule with specialized converter to the
1032 1067
    /// writer.
1033 1068
    template <typename Map, typename Converter>
1034 1069
    GraphWriter& edgeMap(const std::string& caption, const Map& map, 
1035 1070
			  const Converter& converter = Converter()) {
1036 1071
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1037 1072
      _writer_bits::MapStorageBase<Edge>* storage = 
1038 1073
	new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1039 1074
      _edge_maps.push_back(std::make_pair(caption, storage));
1040 1075
      return *this;
1041 1076
    }
1042 1077

	
1043 1078
    /// \brief Arc map writing rule
1044 1079
    ///
1045 1080
    /// Add an arc map writing rule to the writer.
1046 1081
    template <typename Map>
1047 1082
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1048 1083
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1049 1084
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
1050 1085
	new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1051 1086
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1052 1087
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
1053 1088
	new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1054 1089
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1055 1090
      return *this;
1056 1091
    }
1057 1092

	
1058 1093
    /// \brief Arc map writing rule
1059 1094
    ///
1060 1095
    /// Add an arc map writing rule with specialized converter to the
1061 1096
    /// writer.
1062 1097
    template <typename Map, typename Converter>
1063 1098
    GraphWriter& arcMap(const std::string& caption, const Map& map, 
1064 1099
			  const Converter& converter = Converter()) {
1065 1100
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1066 1101
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
1067 1102
	new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1068 1103
	(_graph, map, converter);
1069 1104
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1070 1105
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
1071 1106
	new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1072 1107
	(_graph, map, converter);
1073 1108
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1074 1109
      return *this;
1075 1110
    }
1076 1111

	
1077 1112
    /// \brief Attribute writing rule
1078 1113
    ///
1079 1114
    /// Add an attribute writing rule to the writer.
1080 1115
    template <typename Value>
1081 1116
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1082 1117
      _writer_bits::ValueStorageBase* storage = 
1083 1118
	new _writer_bits::ValueStorage<Value>(value);
1084 1119
      _attributes.push_back(std::make_pair(caption, storage));
1085 1120
      return *this;
1086 1121
    }
1087 1122

	
1088 1123
    /// \brief Attribute writing rule
1089 1124
    ///
1090 1125
    /// Add an attribute writing rule with specialized converter to the
1091 1126
    /// writer.
1092 1127
    template <typename Value, typename Converter>
1093 1128
    GraphWriter& attribute(const std::string& caption, const Value& value, 
1094 1129
			     const Converter& converter = Converter()) {
1095 1130
      _writer_bits::ValueStorageBase* storage = 
1096 1131
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1097 1132
      _attributes.push_back(std::make_pair(caption, storage));
1098 1133
      return *this;
1099 1134
    }
1100 1135

	
1101 1136
    /// \brief Node writing rule
1102 1137
    ///
1103 1138
    /// Add a node writing rule to the writer.
1104 1139
    GraphWriter& node(const std::string& caption, const Node& node) {
1105 1140
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1106 1141
      Converter converter(_node_index);
1107 1142
      _writer_bits::ValueStorageBase* storage = 
1108 1143
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1109 1144
      _attributes.push_back(std::make_pair(caption, storage));
1110 1145
      return *this;
1111 1146
    }
1112 1147

	
1113 1148
    /// \brief Edge writing rule
1114 1149
    ///
1115 1150
    /// Add an edge writing rule to writer.
1116 1151
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1117 1152
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1118 1153
      Converter converter(_edge_index);
1119 1154
      _writer_bits::ValueStorageBase* storage = 
1120 1155
	new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1121 1156
      _attributes.push_back(std::make_pair(caption, storage));
1122 1157
      return *this;
1123 1158
    }
1124 1159

	
1125 1160
    /// \brief Arc writing rule
1126 1161
    ///
1127 1162
    /// Add an arc writing rule to writer.
1128 1163
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1129 1164
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1130 1165
      Converter converter(_graph, _edge_index);
1131 1166
      _writer_bits::ValueStorageBase* storage = 
1132 1167
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1133 1168
      _attributes.push_back(std::make_pair(caption, storage));
1134 1169
      return *this;
1135 1170
    }
1136 1171

	
1137 1172
    /// \name Select section by name
1138 1173
    /// @{
1139 1174

	
1140 1175
    /// \brief Set \c \@nodes section to be read
1141 1176
    ///
1142 1177
    /// Set \c \@nodes section to be read
1143 1178
    GraphWriter& nodes(const std::string& caption) {
1144 1179
      _nodes_caption = caption;
1145 1180
      return *this;
1146 1181
    }
1147 1182

	
1148 1183
    /// \brief Set \c \@edges section to be read
1149 1184
    ///
1150 1185
    /// Set \c \@edges section to be read
1151 1186
    GraphWriter& edges(const std::string& caption) {
1152 1187
      _edges_caption = caption;
1153 1188
      return *this;
1154 1189
    }
1155 1190

	
1156 1191
    /// \brief Set \c \@attributes section to be read
1157 1192
    ///
1158 1193
    /// Set \c \@attributes section to be read
1159 1194
    GraphWriter& attributes(const std::string& caption) {
1160 1195
      _attributes_caption = caption;
1161 1196
      return *this;
1162 1197
    }
1163 1198

	
1164 1199
    /// \name Skipping section
1165 1200
    /// @{
1166 1201

	
1167 1202
    /// \brief Skip writing the node set
1168 1203
    ///
1169 1204
    /// The \c \@nodes section will be not written to the stream.
1170 1205
    GraphWriter& skipNodes() {
1171 1206
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1172 1207
      _skip_nodes = true;
1173 1208
      return *this;
1174 1209
    }
1175 1210

	
... ...
@@ -1221,213 +1256,213 @@
1221 1256
	_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1222 1257
	std::sort(nodes.begin(), nodes.end(), id_less);
1223 1258
      } else {
1224 1259
	label->sort(nodes);
1225 1260
      }
1226 1261

	
1227 1262
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1228 1263
	Node n = nodes[i];
1229 1264
	if (label == 0) {
1230 1265
	  std::ostringstream os;
1231 1266
	  os << _graph.id(n);
1232 1267
	  _writer_bits::writeToken(*_os, os.str());
1233 1268
	  *_os << '\t';
1234 1269
	  _node_index.insert(std::make_pair(n, os.str()));
1235 1270
	}
1236 1271
	for (typename NodeMaps::iterator it = _node_maps.begin();
1237 1272
	     it != _node_maps.end(); ++it) {
1238 1273
	  std::string value = it->second->get(n);
1239 1274
	  _writer_bits::writeToken(*_os, value);
1240 1275
	  if (it->first == "label") {
1241 1276
	    _node_index.insert(std::make_pair(n, value));
1242 1277
	  }
1243 1278
	  *_os << '\t';
1244 1279
	}
1245 1280
	*_os << std::endl;
1246 1281
      }
1247 1282
    }
1248 1283

	
1249 1284
    void createNodeIndex() {
1250 1285
      _writer_bits::MapStorageBase<Node>* label = 0;
1251 1286
      for (typename NodeMaps::iterator it = _node_maps.begin();
1252 1287
	   it != _node_maps.end(); ++it) {
1253 1288
        if (it->first == "label") {
1254 1289
	  label = it->second;
1255 1290
	  break;
1256 1291
	}
1257 1292
      }
1258 1293

	
1259 1294
      if (label == 0) {
1260 1295
	for (NodeIt n(_graph); n != INVALID; ++n) {
1261 1296
	  std::ostringstream os;
1262 1297
	  os << _graph.id(n);
1263 1298
	  _node_index.insert(std::make_pair(n, os.str()));	  
1264 1299
	}	
1265 1300
      } else {
1266 1301
	for (NodeIt n(_graph); n != INVALID; ++n) {
1267 1302
	  std::string value = label->get(n);	  
1268 1303
	  _node_index.insert(std::make_pair(n, value));
1269 1304
	}
1270 1305
      }
1271 1306
    }
1272 1307

	
1273 1308
    void writeEdges() {
1274 1309
      _writer_bits::MapStorageBase<Edge>* label = 0;
1275 1310
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1276 1311
	   it != _edge_maps.end(); ++it) {
1277 1312
        if (it->first == "label") {
1278 1313
	  label = it->second;
1279 1314
	  break;
1280 1315
	}
1281 1316
      }
1282 1317

	
1283 1318
      *_os << "@edges";
1284 1319
      if (!_edges_caption.empty()) {
1285 1320
	_writer_bits::writeToken(*_os << ' ', _edges_caption);
1286 1321
      }
1287 1322
      *_os << std::endl;
1288 1323

	
1289 1324
      *_os << '\t' << '\t';
1290 1325
      if (label == 0) {
1291 1326
	*_os << "label" << '\t';
1292 1327
      }
1293 1328
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1294 1329
	   it != _edge_maps.end(); ++it) {
1295 1330
	_writer_bits::writeToken(*_os, it->first) << '\t';
1296 1331
      }
1297 1332
      *_os << std::endl;
1298 1333

	
1299 1334
      std::vector<Edge> edges;
1300 1335
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1301 1336
	edges.push_back(n);
1302 1337
      }
1303 1338
      
1304 1339
      if (label == 0) {
1305 1340
	IdMap<Graph, Edge> id_map(_graph);
1306 1341
	_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1307 1342
	std::sort(edges.begin(), edges.end(), id_less);
1308 1343
      } else {
1309 1344
	label->sort(edges);
1310 1345
      }
1311 1346

	
1312 1347
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1313 1348
	Edge e = edges[i];
1314 1349
	_writer_bits::writeToken(*_os, _node_index.
1315 1350
				 find(_graph.u(e))->second);
1316 1351
	*_os << '\t';
1317 1352
	_writer_bits::writeToken(*_os, _node_index.
1318 1353
				 find(_graph.v(e))->second);
1319 1354
	*_os << '\t';
1320 1355
	if (label == 0) {
1321 1356
	  std::ostringstream os;
1322 1357
	  os << _graph.id(e);
1323 1358
	  _writer_bits::writeToken(*_os, os.str());
1324 1359
	  *_os << '\t';
1325 1360
	  _edge_index.insert(std::make_pair(e, os.str()));
1326 1361
	}
1327 1362
	for (typename EdgeMaps::iterator it = _edge_maps.begin();
1328 1363
	     it != _edge_maps.end(); ++it) {
1329 1364
	  std::string value = it->second->get(e);
1330 1365
	  _writer_bits::writeToken(*_os, value);
1331 1366
	  if (it->first == "label") {
1332 1367
	    _edge_index.insert(std::make_pair(e, value));
1333 1368
	  }
1334 1369
	  *_os << '\t';
1335 1370
	}
1336 1371
	*_os << std::endl;
1337 1372
      }
1338 1373
    }
1339 1374

	
1340 1375
    void createEdgeIndex() {
1341 1376
      _writer_bits::MapStorageBase<Edge>* label = 0;
1342 1377
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1343 1378
	   it != _edge_maps.end(); ++it) {
1344 1379
        if (it->first == "label") {
1345 1380
	  label = it->second;
1346 1381
	  break;
1347 1382
	}
1348 1383
      }
1349 1384

	
1350 1385
      if (label == 0) {
1351 1386
	for (EdgeIt e(_graph); e != INVALID; ++e) {
1352 1387
	  std::ostringstream os;
1353 1388
	  os << _graph.id(e);
1354 1389
	  _edge_index.insert(std::make_pair(e, os.str()));	  
1355 1390
	}	
1356 1391
      } else {
1357 1392
	for (EdgeIt e(_graph); e != INVALID; ++e) {
1358 1393
	  std::string value = label->get(e);	  
1359 1394
	  _edge_index.insert(std::make_pair(e, value));
1360 1395
	}
1361 1396
      }
1362 1397
    }
1363 1398

	
1364 1399
    void writeAttributes() {
1365 1400
      if (_attributes.empty()) return;
1366 1401
      *_os << "@attributes";
1367 1402
      if (!_attributes_caption.empty()) {
1368 1403
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
1369 1404
      }
1370 1405
      *_os << std::endl;
1371 1406
      for (typename Attributes::iterator it = _attributes.begin();
1372 1407
	   it != _attributes.end(); ++it) {
1373 1408
	_writer_bits::writeToken(*_os, it->first) << ' ';
1374 1409
	_writer_bits::writeToken(*_os, it->second->get());
1375 1410
	*_os << std::endl;
1376 1411
      }
1377 1412
    }
1378 1413
    
1379 1414
  public:
1380 1415
    
1381 1416
    /// \name Execution of the writer    
1382 1417
    /// @{
1383 1418

	
1384 1419
    /// \brief Start the batch processing
1385 1420
    ///
1386 1421
    /// This function starts the batch processing
1387 1422
    void run() {
1388 1423
      if (!_skip_nodes) {
1389 1424
	writeNodes();
1390 1425
      } else {
1391 1426
	createNodeIndex();
1392 1427
      }
1393 1428
      if (!_skip_edges) {      
1394 1429
	writeEdges();
1395 1430
      } else {
1396 1431
	createEdgeIndex();
1397 1432
      }
1398 1433
      writeAttributes();
1399 1434
    }
1400 1435

	
1401 1436
    /// \brief Gives back the stream of the writer
1402 1437
    ///
1403 1438
    /// Gives back the stream of the writer
1404 1439
    std::ostream& ostream() {
1405 1440
      return *_os;
1406 1441
    }
1407 1442

	
1408 1443
    /// @}
1409 1444
  };
1410 1445

	
1411 1446
  /// \relates GraphWriter
1412 1447
  template <typename Graph>
1413
  GraphWriter<Graph> graphWriter(std::ostream& os, Graph& graph) {
1448
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph) {
1414 1449
    GraphWriter<Graph> tmp(os, graph);
1415 1450
    return tmp;
1416 1451
  }
1417 1452

	
1418 1453
  /// \relates GraphWriter
1419 1454
  template <typename Graph>
1420
  GraphWriter<Graph> graphWriter(const std::string& fn, Graph& graph) {
1455
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph) {
1421 1456
    GraphWriter<Graph> tmp(fn, graph);
1422 1457
    return tmp;
1423 1458
  }
1424 1459

	
1425 1460
  /// \relates GraphWriter
1426 1461
  template <typename Graph>
1427
  GraphWriter<Graph> graphWriter(const char* fn, Graph& graph) {
1462
  GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) {
1428 1463
    GraphWriter<Graph> tmp(fn, graph);
1429 1464
    return tmp;
1430 1465
  }
1431 1466
}
1432 1467

	
1433 1468
#endif
0 comments (0 inline)