gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
More flexible header names in .lgf + largely improved doc
0 4 1
default
5 files changed with 387 insertions and 100 deletions:
↑ Collapse diff ↑
Ignore white space 16 line context
1
/* -*- C++ -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
namespace lemon {
20
/*!
21

	
22

	
23

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

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

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

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

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

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

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

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

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

	
81
The \c \@edges is just a synonym of \c \@arcs.
82

	
83
The \c \@attributes section contains key-value pairs, each line
84
consists of two tokens, an attribute name, and then an attribute value.
85

	
86
\code
87
 @attributes
88
 source 1
89
 target 3
90
 caption "LEMON test digraph"
91
\endcode
92

	
93
*/
94
}
95

	
96
//  LocalWords:  whitespace whitespaces
Ignore white space 16 line context
1 1
EXTRA_DIST += \
2 2
	doc/Doxyfile.in \
3 3
	doc/coding_style.dox \
4 4
	doc/dirs.dox \
5 5
	doc/groups.dox \
6
	doc/lgf.dox \
6 7
	doc/license.dox \
7 8
	doc/mainpage.dox \
8 9
	doc/namespaces.dox \
9 10
	doc/html
10 11

	
11 12
DOC_EPS_IMAGES18 = \
12 13
	nodeshape_0.eps \
13 14
	nodeshape_1.eps \
Ignore white space 16 line context
... ...
@@ -478,35 +478,16 @@
478 478
\brief Reading and writing LEMON format
479 479

	
480 480
This group describes methods for reading and writing LEMON format. 
481 481
You can find more about this format on the \ref graph-io-page "Graph Input-Output"
482 482
tutorial pages.
483 483
*/
484 484

	
485 485
/**
486
@defgroup section_io Section readers and writers
487
@ingroup lemon_io
488
\brief Section readers and writers for LEMON Input-Output.
489

	
490
This group describes section reader and writer classes that can be 
491
attached to \ref LemonReader and \ref LemonWriter.
492
*/
493

	
494
/**
495
@defgroup item_io Item readers and writers
496
@ingroup lemon_io
497
\brief Item readers and writers for LEMON Input-Output.
498

	
499
This group describes reader and writer classes for various data types
500
(e.g. map or attribute values). These classes can be attached to
501
\ref LemonReader and \ref LemonWriter.
502
*/
503

	
504
/**
505 486
@defgroup eps_io Postscript exporting
506 487
@ingroup io_group
507 488
\brief General \c EPS drawer and graph exporter
508 489

	
509 490
This group describes general \c EPS drawing methods and special
510 491
graph exporting tools. 
511 492
*/
512 493

	
Ignore white space 16 line context
... ...
@@ -263,45 +263,68 @@
263 263
	  is.clear();
264 264
	} else {
265 265
	  is.putback(c);
266 266
	}
267 267
      }
268 268
      str = os.str();
269 269
      return is;
270 270
    }
271

	
272
    std::istream& readIdentifier(std::istream& is, std::string& str) {
273
      std::ostringstream os;
274

	
275
      char c;
276
      is >> std::ws;
277
      
278
      if (!is.get(c))
279
	return is;
280

	
281
      if (!isIdentifierFirstChar(c))
282
	throw DataFormatError("Wrong char in identifier");
283
      
284
      os << c;
285
      
286
      while (is.get(c) && !isWhiteSpace(c)) {
287
	if (!isIdentifierChar(c)) 
288
	  throw DataFormatError("Wrong char in identifier");	  
289
	os << c;
290
      }
291
      if (!is) is.clear();
292
     
293
      str = os.str();
294
      return is;
295
    }
296 271
    
297 272
  }
298
  
299
  /// \e
273

	
274
  /// \ingroup lemon_io
275
  ///  
276
  /// \brief LGF reader for directed graphs
277
  ///
278
  /// This utility reads an \ref lgf-format "LGF" file.
279
  ///
280
  /// The reading method does a batch processing. The user creates a
281
  /// reader object, then various reading rules can be added to the
282
  /// reader, and eventually the reading is executed with the \c run()
283
  /// member function. A map reading rule can be added to the reader
284
  /// with the \c nodeMap() or \c arcMap() members. An optional
285
  /// converter parameter can also be added as a standard functor converting from
286
  /// std::string to the value type of the map. If it is set, it will
287
  /// determine how the tokens in the file should be is converted to the map's
288
  /// value type. If the functor is not set, then a default conversion
289
  /// will be used. One map can be read into multiple map objects at the
290
  /// same time. The \c attribute(), \c node() and \c arc() functions
291
  /// are used to add attribute reading rules.
292
  ///
293
  ///\code
294
  ///     DigraphReader<Digraph>(std::cin, digraph).
295
  ///       nodeMap("coordinates", coord_map).
296
  ///       arcMap("capacity", cap_map).
297
  ///       node("source", src).
298
  ///       node("target", trg).
299
  ///       attribute("caption", caption).
300
  ///       run();
301
  ///\endcode
302
  ///
303
  /// By default the reader uses the first section in the file of the
304
  /// proper type. If a section has an optional name, then it can be
305
  /// selected for reading by giving an optional name parameter to
306
  /// the \c nodes(), \c arcs() or \c attributes()
307
  /// functions.
308
  ///
309
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
310
  /// that the nodes or arcs should not be constructed (added to the
311
  /// graph) during the reading, but instead the label map of the items
312
  /// are given as a parameter of these functions. An
313
  /// application of these function is multipass reading, which is
314
  /// important if two \e \@arcs sections must be read from the
315
  /// file. In this example the first phase would read the node set and one
316
  /// of the arc sets, while the second phase would read the second arc
317
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
318
  /// The previously read label node map should be passed to the \c
319
  /// useNodes() functions. Another application of multipass reading when
320
  /// paths are given as a node map or an arc map. It is impossible read this in
321
  /// a single pass, because the arcs are not constructed when the node
322
  /// maps are read.
300 323
  template <typename _Digraph>
301 324
  class DigraphReader {
302 325
  public:
303 326

	
304 327
    typedef _Digraph Digraph;
305 328
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
306 329
    
307 330
  private:
... ...
@@ -336,33 +359,44 @@
336 359
    bool _use_nodes;
337 360
    bool _use_arcs;
338 361

	
339 362
    int line_num;
340 363
    std::istringstream line;
341 364

	
342 365
  public:
343 366

	
344
    /// \e
367
    /// \brief Constructor
368
    ///
369
    /// Construct a directed graph reader, which reads from the given
370
    /// input stream.
345 371
    DigraphReader(std::istream& is, Digraph& digraph) 
346 372
      : _is(&is), local_is(false), _digraph(digraph),
347 373
	_use_nodes(false), _use_arcs(false) {}
348 374

	
349
    /// \e
375
    /// \brief Constructor
376
    ///
377
    /// Construct a directed graph reader, which reads from the given
378
    /// file.
350 379
    DigraphReader(const std::string& fn, Digraph& digraph) 
351 380
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
352 381
    	_use_nodes(false), _use_arcs(false) {}
353

	
354

	
355
    /// \e
382
    
383
    /// \brief Constructor
384
    ///
385
    /// Construct a directed graph reader, which reads from the given
386
    /// file.
356 387
    DigraphReader(const char* fn, Digraph& digraph) 
357 388
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
358 389
    	_use_nodes(false), _use_arcs(false) {}
359 390

	
360
    /// \e
391
    /// \brief Copy constructor
392
    ///
393
    /// The copy constructor transfers all data from the other reader,
394
    /// therefore the copied reader will not be usable more. 
361 395
    DigraphReader(DigraphReader& other) 
362 396
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
363 397
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) {
364 398

	
365 399
      other.is = 0;
366 400
      other.local_is = false;
367 401
      
368 402
      _node_index.swap(other._node_index);
... ...
@@ -372,17 +406,17 @@
372 406
      _arc_maps.swap(other._arc_maps);
373 407
      _attributes.swap(other._attributes);
374 408

	
375 409
      _nodes_caption = other._nodes_caption;
376 410
      _arcs_caption = other._arcs_caption;
377 411
      _attributes_caption = other._attributes_caption;
378 412
    }
379 413

	
380
    /// \e
414
    /// \brief Destructor
381 415
    ~DigraphReader() {
382 416
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
383 417
	   it != _node_maps.end(); ++it) {
384 418
	delete it->second;
385 419
      }
386 420

	
387 421
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
388 422
	   it != _arc_maps.end(); ++it) {
... ...
@@ -401,167 +435,221 @@
401 435
    }
402 436

	
403 437
  private:
404 438
    
405 439
    DigraphReader& operator=(const DigraphReader&);
406 440

	
407 441
  public:
408 442

	
409
    /// \e
443
    /// \name Reading rules
444
    /// @{
445
    
446
    /// \brief Node map reading rule
447
    ///
448
    /// Add a node map reading rule to the reader.
410 449
    template <typename Map>
411 450
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
412 451
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
413 452
      _reader_bits::MapStorageBase<Node>* storage = 
414 453
	new _reader_bits::MapStorage<Node, Map>(map);
415 454
      _node_maps.push_back(std::make_pair(caption, storage));
416 455
      return *this;
417 456
    }
418 457

	
419
    /// \e
458
    /// \brief Node map reading rule
459
    ///
460
    /// Add a node map reading rule with specialized converter to the
461
    /// reader.
420 462
    template <typename Map, typename Converter>
421 463
    DigraphReader& nodeMap(const std::string& caption, Map& map, 
422 464
			   const Converter& converter = Converter()) {
423 465
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
424 466
      _reader_bits::MapStorageBase<Node>* storage = 
425 467
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
426 468
      _node_maps.push_back(std::make_pair(caption, storage));
427 469
      return *this;
428 470
    }
429 471

	
430
    /// \e
472
    /// \brief Arc map reading rule
473
    ///
474
    /// Add an arc map reading rule to the reader.
431 475
    template <typename Map>
432 476
    DigraphReader& arcMap(const std::string& caption, Map& map) {
433 477
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
434 478
      _reader_bits::MapStorageBase<Arc>* storage = 
435 479
	new _reader_bits::MapStorage<Arc, Map>(map);
436 480
      _arc_maps.push_back(std::make_pair(caption, storage));
437 481
      return *this;
438 482
    }
439 483

	
440
    /// \e
484
    /// \brief Arc map reading rule
485
    ///
486
    /// Add an arc map reading rule with specialized converter to the
487
    /// reader.
441 488
    template <typename Map, typename Converter>
442 489
    DigraphReader& arcMap(const std::string& caption, Map& map, 
443 490
			  const Converter& converter = Converter()) {
444 491
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
445 492
      _reader_bits::MapStorageBase<Arc>* storage = 
446 493
	new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
447 494
      _arc_maps.push_back(std::make_pair(caption, storage));
448 495
      return *this;
449 496
    }
450 497

	
451
    /// \e
498
    /// \brief Attribute reading rule
499
    ///
500
    /// Add an attribute reading rule to the reader.
452 501
    template <typename Value>
453 502
    DigraphReader& attribute(const std::string& caption, Value& value) {
454 503
      _reader_bits::ValueStorageBase* storage = 
455 504
	new _reader_bits::ValueStorage<Value>(value);
456 505
      _attributes.insert(std::make_pair(caption, storage));
457 506
      return *this;
458 507
    }
459 508

	
460
    /// \e
509
    /// \brief Attribute reading rule
510
    ///
511
    /// Add an attribute reading rule with specialized converter to the
512
    /// reader.
461 513
    template <typename Value, typename Converter>
462 514
    DigraphReader& attribute(const std::string& caption, Value& value, 
463 515
			     const Converter& converter = Converter()) {
464 516
      _reader_bits::ValueStorageBase* storage = 
465 517
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
466 518
      _attributes.insert(std::make_pair(caption, storage));
467 519
      return *this;
468 520
    }
469 521

	
470
    /// \e
522
    /// \brief Node reading rule
523
    ///
524
    /// Add a node reading rule to reader.
471 525
    DigraphReader& node(const std::string& caption, Node& node) {
472 526
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
473 527
      Converter converter(_node_index);
474 528
      _reader_bits::ValueStorageBase* storage = 
475 529
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
476 530
      _attributes.insert(std::make_pair(caption, storage));
477 531
      return *this;
478 532
    }
479 533

	
480
    /// \e
534
    /// \brief Arc reading rule
535
    ///
536
    /// Add an arc reading rule to reader.
481 537
    DigraphReader& arc(const std::string& caption, Arc& arc) {
482 538
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
483 539
      Converter converter(_arc_index);
484 540
      _reader_bits::ValueStorageBase* storage = 
485 541
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
486 542
      _attributes.insert(std::make_pair(caption, storage));
487 543
      return *this;
488 544
    }
489 545

	
490
    /// \e
546
    /// @}
547

	
548
    /// \name Select section by name
549
    /// @{
550

	
551
    /// \brief Set \c \@nodes section to be read
552
    ///
553
    /// Set \c \@nodes section to be read
491 554
    DigraphReader& nodes(const std::string& caption) {
492 555
      _nodes_caption = caption;
493 556
      return *this;
494 557
    }
495 558

	
496
    /// \e
559
    /// \brief Set \c \@arcs section to be read
560
    ///
561
    /// Set \c \@arcs section to be read
497 562
    DigraphReader& arcs(const std::string& caption) {
498 563
      _arcs_caption = caption;
499 564
      return *this;
500 565
    }
501 566

	
502
    /// \e
567
    /// \brief Set \c \@attributes section to be read
568
    ///
569
    /// Set \c \@attributes section to be read
503 570
    DigraphReader& attributes(const std::string& caption) {
504 571
      _attributes_caption = caption;
505 572
      return *this;
506 573
    }
507 574

	
508
    /// \e
575
    /// @}
576

	
577
    /// \name Using previously constructed node or arc set
578
    /// @{
579

	
580
    /// \brief Use previously constructed node set
581
    ///
582
    /// Use previously constructed node set, and specify the node
583
    /// label map.
509 584
    template <typename Map>
510 585
    DigraphReader& useNodes(const Map& map) {
511 586
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
512 587
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
513 588
      _use_nodes = true;
514 589
      _writer_bits::DefaultConverter<typename Map::Value> converter;
515 590
      for (NodeIt n(_digraph); n != INVALID; ++n) {
516 591
	_node_index.insert(std::make_pair(converter(map[n]), n));
517 592
      }
518 593
      return *this;
519 594
    }
520 595

	
521
    /// \e
596
    /// \brief Use previously constructed node set
597
    ///
598
    /// Use previously constructed node set, and specify the node
599
    /// label map and a functor which converts the label map values to
600
    /// std::string.
522 601
    template <typename Map, typename Converter>
523 602
    DigraphReader& useNodes(const Map& map, 
524 603
			    const Converter& converter = Converter()) {
525 604
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
526 605
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
527 606
      _use_nodes = true;
528 607
      for (NodeIt n(_digraph); n != INVALID; ++n) {
529 608
	_node_index.insert(std::make_pair(converter(map[n]), n));
530 609
      }
531 610
      return *this;
532 611
    }
533 612

	
534
    /// \e
613
    /// \brief Use previously constructed arc set
614
    ///
615
    /// Use previously constructed arc set, and specify the arc
616
    /// label map.
535 617
    template <typename Map>
536 618
    DigraphReader& useArcs(const Map& map) {
537 619
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
538 620
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
539 621
      _use_arcs = true;
540 622
      _writer_bits::DefaultConverter<typename Map::Value> converter;
541 623
      for (ArcIt a(_digraph); a != INVALID; ++a) {
542 624
	_arc_index.insert(std::make_pair(converter(map[a]), a));
543 625
      }
544 626
      return *this;
545 627
    }
546 628

	
547
    /// \e
629
    /// \brief Use previously constructed arc set
630
    ///
631
    /// Use previously constructed arc set, and specify the arc
632
    /// label map and a functor which converts the label map values to
633
    /// std::string.
548 634
    template <typename Map, typename Converter>
549 635
    DigraphReader& useArcs(const Map& map, 
550 636
			    const Converter& converter = Converter()) {
551 637
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
552 638
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
553 639
      _use_arcs = true;
554 640
      for (ArcIt a(_digraph); a != INVALID; ++a) {
555 641
	_arc_index.insert(std::make_pair(converter(map[a]), a));
556 642
      }
557 643
      return *this;
558 644
    }
559 645

	
646
    /// @}
647

	
560 648
  private:
561 649

	
562 650
    bool readLine() {
563 651
      std::string str;
564 652
      while(++line_num, std::getline(*_is, str)) {
565 653
	line.clear(); line.str(str);
566 654
	char c;
567 655
	if (line >> std::ws >> c && c != '#') {
... ...
@@ -592,17 +680,17 @@
592 680
      if (!readLine()) 
593 681
	throw DataFormatError("Cannot find map captions");
594 682
      
595 683
      {
596 684
	std::map<std::string, int> maps;
597 685
	
598 686
	std::string map;
599 687
	int index = 0;
600
	while (_reader_bits::readIdentifier(line, map)) {
688
	while (_reader_bits::readToken(line, map)) {
601 689
	  if (maps.find(map) != maps.end()) {
602 690
	    std::ostringstream msg;
603 691
	    msg << "Multiple occurence of node map: " << map;
604 692
	    throw DataFormatError(msg.str().c_str());
605 693
	  }
606 694
	  maps.insert(std::make_pair(map, index));
607 695
	  ++index;
608 696
	}
... ...
@@ -675,17 +763,17 @@
675 763
      if (!readLine()) 
676 764
	throw DataFormatError("Cannot find map captions");
677 765
      
678 766
      {
679 767
	std::map<std::string, int> maps;
680 768
	
681 769
	std::string map;
682 770
	int index = 0;
683
	while (_reader_bits::readIdentifier(line, map)) {
771
	while (_reader_bits::readToken(line, map)) {
684 772
	  if (maps.find(map) != maps.end()) {
685 773
	    std::ostringstream msg;
686 774
	    msg << "Multiple occurence of arc map: " << map;
687 775
	    throw DataFormatError(msg.str().c_str());
688 776
	  }
689 777
	  maps.insert(std::make_pair(map, index));
690 778
	  ++index;
691 779
	}
... ...
@@ -782,17 +870,17 @@
782 870

	
783 871
      std::set<std::string> read_attr;
784 872

	
785 873
      char c;
786 874
      while (readLine() && line >> c && c != '@') {
787 875
	line.putback(c);
788 876
	
789 877
	std::string attr, token;
790
	if (!_reader_bits::readIdentifier(line, attr))
878
	if (!_reader_bits::readToken(line, attr))
791 879
	  throw DataFormatError("Attribute name not found");
792 880
	if (!_reader_bits::readToken(line, token))
793 881
	  throw DataFormatError("Attribute value not found");
794 882
	if (line >> c)
795 883
	  throw DataFormatError("Extra character on the end of line");	  
796 884

	
797 885
	{
798 886
	  std::set<std::string>::iterator it = read_attr.find(attr);
... ...
@@ -822,18 +910,23 @@
822 910
	  std::ostringstream msg;
823 911
	  msg << "Attribute not found in file: " << it->first;
824 912
	  throw DataFormatError(msg.str().c_str());
825 913
	}	
826 914
      }
827 915
    }
828 916

	
829 917
  public:
830
    
831
    /// \e
918

	
919
    /// \name Execution of the reader    
920
    /// @{
921

	
922
    /// \brief Start the batch processing
923
    ///
924
    /// This function starts the batch processing
832 925
    void run() {
833 926
      
834 927
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
835 928
      
836 929
      bool nodes_done = false;
837 930
      bool arcs_done = false;
838 931
      bool attributes_done = false;
839 932

	
... ...
@@ -841,18 +934,18 @@
841 934
      readLine();
842 935

	
843 936
      while (readSuccess()) {
844 937
	skipSection();
845 938
	try {
846 939
	  char c;
847 940
	  std::string section, caption;
848 941
	  line >> c;
849
	  _reader_bits::readIdentifier(line, section);
850
	  _reader_bits::readIdentifier(line, caption);
942
	  _reader_bits::readToken(line, section);
943
	  _reader_bits::readToken(line, caption);
851 944

	
852 945
	  if (line >> c) 
853 946
	    throw DataFormatError("Extra character on the end of line");
854 947

	
855 948
	  if (section == "nodes" && !nodes_done) {
856 949
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
857 950
	      readNodes();
858 951
	      nodes_done = true;
... ...
@@ -886,29 +979,34 @@
886 979
	throw DataFormatError("Section @arcs not found");
887 980
      }
888 981

	
889 982
      if (!attributes_done && !_attributes.empty()) {
890 983
	throw DataFormatError("Section @attributes not found");
891 984
      }
892 985

	
893 986
    }
987

	
988
    /// @}
894 989
    
895 990
  };
896 991

	
992
  /// \relates DigraphReader
897 993
  template <typename Digraph>
898 994
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
899 995
    return DigraphReader<Digraph>(is, digraph);
900 996
  }
901 997

	
998
  /// \relates DigraphReader
902 999
  template <typename Digraph>
903 1000
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
904 1001
				       Digraph& digraph) {
905 1002
    return DigraphReader<Digraph>(fn, digraph);
906 1003
  }
907 1004

	
1005
  /// \relates DigraphReader
908 1006
  template <typename Digraph>
909 1007
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
910 1008
    return DigraphReader<Digraph>(fn, digraph);
911 1009
  }
912 1010
}
913 1011

	
914 1012
#endif
Ignore white space 16 line context
... ...
@@ -199,16 +199,17 @@
199 199
	} else {
200 200
	  os << c;
201 201
	}
202 202
	return;
203 203
      }     
204 204
    }
205 205

	
206 206
    bool requireEscape(const std::string& str) {
207
      if (str.empty() || str[0] == '@') return true;
207 208
      std::istringstream is(str);
208 209
      char c;
209 210
      while (is.get(c)) {
210 211
	if (isWhiteSpace(c) || isEscaped(c)) {
211 212
	  return true;
212 213
	}
213 214
      }
214 215
      return false;
... ...
@@ -226,17 +227,60 @@
226 227
      } else {
227 228
	os << str;
228 229
      }
229 230
      return os;
230 231
    }
231 232

	
232 233
  }
233 234
  
234
  /// \e
235
  /// \ingroup lemon_io
236
  ///  
237
  /// \brief LGF writer for directed graphs
238
  ///
239
  /// This utility writes an \ref lgf-format "LGF" file.
240
  ///
241
  /// The writing method does a batch processing. The user creates a
242
  /// writer object, then various writing rules can be added to the
243
  /// writer, and eventually the writing is executed with the \c run()
244
  /// member function. A map writing rule can be added to the writer
245
  /// with the \c nodeMap() or \c arcMap() members. An optional
246
  /// converter parameter can also be added as a standard functor converting from
247
  /// the value type of the map to std::string. If it is set, it will
248
  /// determine how the map's value type is written to the output
249
  /// stream. If the functor is not set, then a default conversion
250
  /// will be used. The \c attribute(), \c node() and \c arc() functions
251
  /// are used to add attribute writing rules.
252
  ///
253
  ///\code
254
  ///     DigraphWriter<Digraph>(std::cout, digraph).
255
  ///       nodeMap("coordinates", coord_map).
256
  ///       nodeMap("size", size).
257
  ///       nodeMap("title", title).
258
  ///       arcMap("capacity", cap_map).
259
  ///       node("source", src).
260
  ///       node("target", trg).
261
  ///       attribute("caption", caption).
262
  ///       run();
263
  ///\endcode
264
  ///
265
  ///
266
  /// By default, the writer does not write additional captions to the
267
  /// sections, but they can be give as an optional parameter of
268
  /// the \c nodes(), \c arcs() or \c
269
  /// attributes() functions.
270
  ///
271
  /// The \c skipNodes() and \c skipArcs() functions forbid the
272
  /// writing of the sections. If two arc sections should be written to the
273
  /// output, it can be done in two passes, the first pass writes the
274
  /// node section and the first arc section, then the second pass
275
  /// skips the node section and writes just the arc section to the
276
  /// stream. The output stream can be retrieved with the \c ostream()
277
  /// function, hence the second pass can append its output to the output of the
278
  /// first pass.
235 279
  template <typename _Digraph>
236 280
  class DigraphWriter {
237 281
  public:
238 282

	
239 283
    typedef _Digraph Digraph;
240 284
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
241 285
    
242 286
  private:
... ...
@@ -268,31 +312,44 @@
268 312
      _writer_bits::ValueStorageBase*> > Attributes;
269 313
    Attributes _attributes;
270 314

	
271 315
    bool _skip_nodes;
272 316
    bool _skip_arcs;
273 317

	
274 318
  public:
275 319

	
276
    /// \e
320
    /// \brief Constructor
321
    ///
322
    /// Construct a directed graph writer, which writes to the given
323
    /// output stream.
277 324
    DigraphWriter(std::ostream& is, Digraph& digraph) 
278 325
      : _os(&is), local_os(false), _digraph(digraph),
279 326
	_skip_nodes(false), _skip_arcs(false) {}
280 327

	
281
    /// \e
328
    /// \brief Constructor
329
    ///
330
    /// Construct a directed graph writer, which writes to the given
331
    /// output file.
282 332
    DigraphWriter(const std::string& fn, Digraph& digraph) 
283 333
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
284 334
	_skip_nodes(false), _skip_arcs(false) {}
285 335

	
286
    /// \e
336
    /// \brief Constructor
337
    ///
338
    /// Construct a directed graph writer, which writes to the given
339
    /// output file.
287 340
    DigraphWriter(const char* fn, Digraph& digraph) 
288 341
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
289 342
	_skip_nodes(false), _skip_arcs(false) {}
290 343

	
344
    /// \brief Copy constructor
345
    ///
346
    /// The copy constructor transfers all data from the other writer,
347
    /// therefore the copied writer will not be usable more. 
291 348
    DigraphWriter(DigraphWriter& other) 
292 349
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
293 350
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
294 351

	
295 352
      other.is = 0;
296 353
      other.local_os = false;
297 354

	
298 355
      _node_index.swap(other._node_index);
... ...
@@ -302,17 +359,17 @@
302 359
      _arc_maps.swap(other._arc_maps);
303 360
      _attributes.swap(other._attributes);
304 361

	
305 362
      _nodes_caption = other._nodes_caption;
306 363
      _arcs_caption = other._arcs_caption;
307 364
      _attributes_caption = other._attributes_caption;
308 365
    }
309 366

	
310
    /// \e
367
    /// \brief Destructor
311 368
    ~DigraphWriter() {
312 369
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
313 370
	   it != _node_maps.end(); ++it) {
314 371
	delete it->second;
315 372
      }
316 373

	
317 374
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
318 375
	   it != _arc_maps.end(); ++it) {
... ...
@@ -330,149 +387,191 @@
330 387
    }
331 388

	
332 389
  private:
333 390
    
334 391
    DigraphWriter& operator=(const DigraphWriter&);
335 392

	
336 393
  public:
337 394

	
338
    /// \e
395
    /// \name Writing rules
396
    /// @{
397
    
398
    /// \brief Node map reading rule
399
    ///
400
    /// Add a node map reading rule to the writer.
339 401
    template <typename Map>
340 402
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
341 403
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
342 404
      _writer_bits::MapStorageBase<Node>* storage = 
343 405
	new _writer_bits::MapStorage<Node, Map>(map);
344 406
      _node_maps.push_back(std::make_pair(caption, storage));
345 407
      return *this;
346 408
    }
347 409

	
348
    /// \e
410
    /// \brief Node map writing rule
411
    ///
412
    /// Add a node map writing rule with specialized converter to the
413
    /// writer.
349 414
    template <typename Map, typename Converter>
350 415
    DigraphWriter& nodeMap(const std::string& caption, const Map& map, 
351 416
			   const Converter& converter = Converter()) {
352 417
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
353 418
      _writer_bits::MapStorageBase<Node>* storage = 
354 419
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
355 420
      _node_maps.push_back(std::make_pair(caption, storage));
356 421
      return *this;
357 422
    }
358 423

	
359
    /// \e
424
    /// \brief Arc map writing rule
425
    ///
426
    /// Add an arc map writing rule to the writer.
360 427
    template <typename Map>
361 428
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
362 429
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
363 430
      _writer_bits::MapStorageBase<Arc>* storage = 
364 431
	new _writer_bits::MapStorage<Arc, Map>(map);
365 432
      _arc_maps.push_back(std::make_pair(caption, storage));
366 433
      return *this;
367 434
    }
368 435

	
369
    /// \e
436
    /// \brief Arc map writing rule
437
    ///
438
    /// Add an arc map writing rule with specialized converter to the
439
    /// writer.
370 440
    template <typename Map, typename Converter>
371 441
    DigraphWriter& arcMap(const std::string& caption, const Map& map, 
372 442
			  const Converter& converter = Converter()) {
373 443
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
374 444
      _writer_bits::MapStorageBase<Arc>* storage = 
375 445
	new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
376 446
      _arc_maps.push_back(std::make_pair(caption, storage));
377 447
      return *this;
378 448
    }
379 449

	
380
    /// \e
450
    /// \brief Attribute writing rule
451
    ///
452
    /// Add an attribute writing rule to the writer.
381 453
    template <typename Value>
382 454
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
383 455
      _writer_bits::ValueStorageBase* storage = 
384 456
	new _writer_bits::ValueStorage<Value>(value);
385 457
      _attributes.push_back(std::make_pair(caption, storage));
386 458
      return *this;
387 459
    }
388 460

	
389
    /// \e
461
    /// \brief Attribute writing rule
462
    ///
463
    /// Add an attribute writing rule with specialized converter to the
464
    /// writer.
390 465
    template <typename Value, typename Converter>
391 466
    DigraphWriter& attribute(const std::string& caption, const Value& value, 
392 467
			     const Converter& converter = Converter()) {
393 468
      _writer_bits::ValueStorageBase* storage = 
394 469
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
395 470
      _attributes.push_back(std::make_pair(caption, storage));
396 471
      return *this;
397 472
    }
398 473

	
399
    /// \e
474
    /// \brief Node writing rule
475
    ///
476
    /// Add a node writing rule to the writer.
400 477
    DigraphWriter& node(const std::string& caption, const Node& node) {
401 478
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
402 479
      Converter converter(_node_index);
403 480
      _writer_bits::ValueStorageBase* storage = 
404 481
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
405 482
      _attributes.push_back(std::make_pair(caption, storage));
406 483
      return *this;
407 484
    }
408 485

	
409
    /// \e
486
    /// \brief Arc writing rule
487
    ///
488
    /// Add an arc writing rule to writer.
410 489
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
411 490
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
412 491
      Converter converter(_arc_index);
413 492
      _writer_bits::ValueStorageBase* storage = 
414 493
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
415 494
      _attributes.push_back(std::make_pair(caption, storage));
416 495
      return *this;
417 496
    }
418 497

	
419
    /// \e
498
    /// \name Select section by name
499
    /// @{
500

	
501
    /// \brief Set \c \@nodes section to be read
502
    ///
503
    /// Set \c \@nodes section to be read
420 504
    DigraphWriter& nodes(const std::string& caption) {
421 505
      _nodes_caption = caption;
422 506
      return *this;
423 507
    }
424 508

	
425
    /// \e
509
    /// \brief Set \c \@arcs section to be read
510
    ///
511
    /// Set \c \@arcs section to be read
426 512
    DigraphWriter& arcs(const std::string& caption) {
427 513
      _arcs_caption = caption;
428 514
      return *this;
429 515
    }
430 516

	
431
    /// \e
517
    /// \brief Set \c \@attributes section to be read
518
    ///
519
    /// Set \c \@attributes section to be read
432 520
    DigraphWriter& attributes(const std::string& caption) {
433 521
      _attributes_caption = caption;
434 522
      return *this;
435 523
    }
436 524

	
525
    /// \name Skipping section
526
    /// @{
527

	
528
    /// \brief Skip writing the node set
529
    ///
530
    /// The \c \@nodes section will be not written to the stream.
437 531
    DigraphWriter& skipNodes() {
438 532
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
439 533
      return *this;
440 534
    }
441 535

	
536
    /// \brief Skip writing arc set
537
    ///
538
    /// The \c \@arcs section will be not written to the stream.
442 539
    DigraphWriter& skipArcs() {
443 540
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
444 541
      return *this;
445 542
    }
446 543

	
544
    /// @}
545

	
447 546
  private:
448 547

	
449 548
    void writeNodes() {
450 549
      _writer_bits::MapStorageBase<Node>* label = 0;
451 550
      for (typename NodeMaps::iterator it = _node_maps.begin();
452 551
	   it != _node_maps.end(); ++it) {
453 552
        if (it->first == "label") {
454 553
	  label = it->second;
455 554
	  break;
456 555
	}
457 556
      }
458 557

	
459 558
      *_os << "@nodes";
460 559
      if (!_nodes_caption.empty()) {
461
	*_os << ' ' << _nodes_caption;
560
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
462 561
      }
463 562
      *_os << std::endl;
464 563

	
465 564
      if (label == 0) {
466 565
	*_os << "label" << '\t';
467 566
      }
468 567
      for (typename NodeMaps::iterator it = _node_maps.begin();
469 568
	   it != _node_maps.end(); ++it) {
470
	*_os << it->first << '\t';
569
	_writer_bits::writeToken(*_os, it->first) << '\t';
471 570
      }
472 571
      *_os << std::endl;
473 572

	
474 573
      std::vector<Node> nodes;
475 574
      for (NodeIt n(_digraph); n != INVALID; ++n) {
476 575
	nodes.push_back(n);
477 576
      }
478 577
      
... ...
@@ -513,27 +612,27 @@
513 612
        if (it->first == "label") {
514 613
	  label = it->second;
515 614
	  break;
516 615
	}
517 616
      }
518 617

	
519 618
      *_os << "@arcs";
520 619
      if (!_arcs_caption.empty()) {
521
	*_os << ' ' << _arcs_caption;
620
	_writer_bits::writeToken(*_os << ' ', _arcs_caption);
522 621
      }
523 622
      *_os << std::endl;
524 623

	
525 624
      *_os << '\t' << '\t';
526 625
      if (label == 0) {
527 626
	*_os << "label" << '\t';
528 627
      }
529 628
      for (typename ArcMaps::iterator it = _arc_maps.begin();
530 629
	   it != _arc_maps.end(); ++it) {
531
	*_os << it->first << '\t';
630
	_writer_bits::writeToken(*_os, it->first) << '\t';
532 631
      }
533 632
      *_os << std::endl;
534 633

	
535 634
      std::vector<Arc> arcs;
536 635
      for (ArcIt n(_digraph); n != INVALID; ++n) {
537 636
	arcs.push_back(n);
538 637
      }
539 638
      
... ...
@@ -572,56 +671,68 @@
572 671
	*_os << std::endl;
573 672
      }
574 673
    }
575 674

	
576 675
    void writeAttributes() {
577 676
      if (_attributes.empty()) return;
578 677
      *_os << "@attributes";
579 678
      if (!_attributes_caption.empty()) {
580
	*_os << ' ' << _attributes_caption;
679
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
581 680
      }
582 681
      *_os << std::endl;
583 682
      for (typename Attributes::iterator it = _attributes.begin();
584 683
	   it != _attributes.end(); ++it) {
585
	*_os << it->first << ' ';
684
	_writer_bits::writeToken(*_os, it->first) << ' ';
586 685
	_writer_bits::writeToken(*_os, it->second->get());
587 686
	*_os << std::endl;
588 687
      }
589 688
    }
590 689
    
591 690
  public:
592 691
    
593
    /// \e
692
    /// \name Execution of the writer    
693
    /// @{
694

	
695
    /// \brief Start the batch processing
696
    ///
697
    /// This function starts the batch processing
594 698
    void run() {
595 699
      if (!_skip_nodes) {
596 700
	writeNodes();
597 701
      }
598 702
      if (!_skip_arcs) {      
599 703
	writeArcs();
600 704
      }
601 705
      writeAttributes();
602 706
    }
603 707

	
604
    /// \e
605
    std::ostream& stream() {
708
    /// \brief Gives back the stream of the writer
709
    ///
710
    /// Gives back the stream of the writer
711
    std::ostream& ostream() {
606 712
      return *_os;
607 713
    }
714

	
715
    /// @}
608 716
  };
609 717

	
718
  /// \relates DigraphWriter
610 719
  template <typename Digraph>
611 720
  DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) {
612 721
    return DigraphWriter<Digraph>(is, digraph);
613 722
  }
614 723

	
724
  /// \relates DigraphWriter
615 725
  template <typename Digraph>
616 726
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
617 727
				       Digraph& digraph) {
618 728
    return DigraphWriter<Digraph>(fn, digraph);
619 729
  }
620 730

	
731
  /// \relates DigraphWriter
621 732
  template <typename Digraph>
622 733
  DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
623 734
    return DigraphWriter<Digraph>(fn, digraph);
624 735
  }
625 736
}
626 737

	
627 738
#endif
0 comments (0 inline)