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

	
19 19
///\ingroup demos
20 20
///\file
21 21
///\brief Demonstrating graph input and output
22 22
///
23 23
/// This program gives an example of how to load a directed graph from
24 24
/// an \ref lgf-format "LGF" file with the \ref lemon::DigraphReader
25 25
/// "DigraphReader" class.
26 26
///
27 27
/// The \c "digraph.lgf" file:
28 28
/// \include digraph.lgf
29 29
///
30 30
/// And the program which reads it:
31 31
/// \include lgf_demo.cc
32 32

	
33 33
#include <iostream>
34 34
#include <lemon/smart_graph.h>
35 35
#include <lemon/lgf_reader.h>
36 36
#include <lemon/lgf_writer.h>
37
#include <lemon/random.h>
38

	
39 37

	
40 38
using namespace lemon;
41 39

	
42 40
int main() {
43 41
  SmartDigraph g;
44 42
  SmartDigraph::ArcMap<int> cap(g);
45 43
  SmartDigraph::Node s, t;
46 44

	
47
  digraphReader("digraph.lgf", g). // read the directeg graph into g
45
  digraphReader("digraph.lgf", g). // read the directed graph into g
48 46
    arcMap("capacity", cap).       // read the 'capacity' arc map into cap
49 47
    node("source", s).             // read 'source' node to s
50 48
    node("target", t).             // read 'target' node to t
51 49
    run();
52 50

	
53
  std::cout << "Digraph read from 'digraph.lgf'" << std::endl;
51
  std::cout << "A digraph is read from 'digraph.lgf'." << std::endl;
54 52
  std::cout << "Number of nodes: " << countNodes(g) << std::endl;
55 53
  std::cout << "Number of arcs: " << countArcs(g) << std::endl;
56 54

	
57 55
  std::cout << "We can write it to the standard output:" << std::endl;
58 56

	
59 57
  digraphWriter(std::cout, g).     // write g to the standard output
60 58
    arcMap("capacity", cap).       // write cap into 'capacity'
61 59
    node("source", s).             // write s to 'source'
62 60
    node("target", t).             // write t to 'target'
63 61
    run();
64 62

	
65 63
  return 0;
66 64
}
Ignore white space 384 line context
... ...
@@ -286,276 +286,274 @@
286 286
/**
287 287
@defgroup graph_prop Connectivity and other graph properties
288 288
@ingroup algs
289 289
\brief Algorithms for discovering the graph properties
290 290

	
291 291
This group describes the algorithms for discovering the graph properties
292 292
like connectivity, bipartiteness, euler property, simplicity etc.
293 293

	
294 294
\image html edge_biconnected_components.png
295 295
\image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth
296 296
*/
297 297

	
298 298
/**
299 299
@defgroup planar Planarity embedding and drawing
300 300
@ingroup algs
301 301
\brief Algorithms for planarity checking, embedding and drawing
302 302

	
303 303
This group describes the algorithms for planarity checking, embedding and drawing.
304 304

	
305 305
\image html planar.png
306 306
\image latex planar.eps "Plane graph" width=\textwidth
307 307
*/
308 308

	
309 309
/**
310 310
@defgroup matching Matching algorithms 
311 311
@ingroup algs
312 312
\brief Algorithms for finding matchings in graphs and bipartite graphs.
313 313

	
314 314
This group contains algorithm objects and functions to calculate
315 315
matchings in graphs and bipartite graphs. The general matching problem is
316 316
finding a subset of the arcs which does not shares common endpoints.
317 317
 
318 318
There are several different algorithms for calculate matchings in
319 319
graphs.  The matching problems in bipartite graphs are generally
320 320
easier than in general graphs. The goal of the matching optimization
321 321
can be the finding maximum cardinality, maximum weight or minimum cost
322 322
matching. The search can be constrained to find perfect or
323 323
maximum cardinality matching.
324 324

	
325 325
Lemon contains the next algorithms:
326 326
- \ref lemon::MaxBipartiteMatching "MaxBipartiteMatching" Hopcroft-Karp 
327 327
  augmenting path algorithm for calculate maximum cardinality matching in 
328 328
  bipartite graphs
329 329
- \ref lemon::PrBipartiteMatching "PrBipartiteMatching" Push-Relabel 
330 330
  algorithm for calculate maximum cardinality matching in bipartite graphs 
331 331
- \ref lemon::MaxWeightedBipartiteMatching "MaxWeightedBipartiteMatching" 
332 332
  Successive shortest path algorithm for calculate maximum weighted matching 
333 333
  and maximum weighted bipartite matching in bipartite graph
334 334
- \ref lemon::MinCostMaxBipartiteMatching "MinCostMaxBipartiteMatching" 
335 335
  Successive shortest path algorithm for calculate minimum cost maximum 
336 336
  matching in bipartite graph
337 337
- \ref lemon::MaxMatching "MaxMatching" Edmond's blossom shrinking algorithm
338 338
  for calculate maximum cardinality matching in general graph
339 339
- \ref lemon::MaxWeightedMatching "MaxWeightedMatching" Edmond's blossom
340 340
  shrinking algorithm for calculate maximum weighted matching in general
341 341
  graph
342 342
- \ref lemon::MaxWeightedPerfectMatching "MaxWeightedPerfectMatching"
343 343
  Edmond's blossom shrinking algorithm for calculate maximum weighted
344 344
  perfect matching in general graph
345 345

	
346 346
\image html bipartite_matching.png
347 347
\image latex bipartite_matching.eps "Bipartite Matching" width=\textwidth
348 348

	
349 349
*/
350 350

	
351 351
/**
352 352
@defgroup spantree Minimum Spanning Tree algorithms
353 353
@ingroup algs
354 354
\brief Algorithms for finding a minimum cost spanning tree in a graph.
355 355

	
356 356
This group describes the algorithms for finding a minimum cost spanning
357 357
tree in a graph
358 358
*/
359 359

	
360 360

	
361 361
/**
362 362
@defgroup auxalg Auxiliary algorithms
363 363
@ingroup algs
364 364
\brief Auxiliary algorithms implemented in LEMON.
365 365

	
366 366
This group describes some algorithms implemented in LEMON
367 367
in order to make it easier to implement complex algorithms.
368 368
*/
369 369

	
370 370
/**
371 371
@defgroup approx Approximation algorithms
372 372
\brief Approximation algorithms.
373 373

	
374 374
This group describes the approximation and heuristic algorithms
375 375
implemented in LEMON.
376 376
*/
377 377

	
378 378
/**
379 379
@defgroup gen_opt_group General Optimization Tools
380 380
\brief This group describes some general optimization frameworks
381 381
implemented in LEMON.
382 382

	
383 383
This group describes some general optimization frameworks
384 384
implemented in LEMON.
385 385

	
386 386
*/
387 387

	
388 388
/**
389 389
@defgroup lp_group Lp and Mip solvers
390 390
@ingroup gen_opt_group
391 391
\brief Lp and Mip solver interfaces for LEMON.
392 392

	
393 393
This group describes Lp and Mip solver interfaces for LEMON. The
394 394
various LP solvers could be used in the same manner with this
395 395
interface.
396 396

	
397 397
*/
398 398

	
399 399
/** 
400 400
@defgroup lp_utils Tools for Lp and Mip solvers 
401 401
@ingroup lp_group
402 402
\brief Helper tools to the Lp and Mip solvers.
403 403

	
404 404
This group adds some helper tools to general optimization framework
405 405
implemented in LEMON.
406 406
*/
407 407

	
408 408
/**
409 409
@defgroup metah Metaheuristics
410 410
@ingroup gen_opt_group
411 411
\brief Metaheuristics for LEMON library.
412 412

	
413 413
This group describes some metaheuristic optimization tools.
414 414
*/
415 415

	
416 416
/**
417 417
@defgroup utils Tools and Utilities 
418 418
\brief Tools and utilities for programming in LEMON
419 419

	
420 420
Tools and utilities for programming in LEMON.
421 421
*/
422 422

	
423 423
/**
424 424
@defgroup gutils Basic Graph Utilities
425 425
@ingroup utils
426 426
\brief Simple basic graph utilities.
427 427

	
428 428
This group describes some simple basic graph utilities.
429 429
*/
430 430

	
431 431
/**
432 432
@defgroup misc Miscellaneous Tools
433 433
@ingroup utils
434 434
\brief Tools for development, debugging and testing.
435 435

	
436 436
This group describes several useful tools for development,
437 437
debugging and testing.
438 438
*/
439 439

	
440 440
/**
441 441
@defgroup timecount Time measuring and Counting
442 442
@ingroup misc
443 443
\brief Simple tools for measuring the performance of algorithms.
444 444

	
445 445
This group describes simple tools for measuring the performance
446 446
of algorithms.
447 447
*/
448 448

	
449 449
/**
450 450
@defgroup graphbits Tools for Graph Implementation
451 451
@ingroup utils
452 452
\brief Tools to make it easier to create graphs.
453 453

	
454 454
This group describes the tools that makes it easier to create graphs and
455 455
the maps that dynamically update with the graph changes.
456 456
*/
457 457

	
458 458
/**
459 459
@defgroup exceptions Exceptions
460 460
@ingroup utils
461 461
\brief Exceptions defined in LEMON.
462 462

	
463 463
This group describes the exceptions defined in LEMON.
464 464
*/
465 465

	
466 466
/**
467 467
@defgroup io_group Input-Output
468 468
\brief Graph Input-Output methods
469 469

	
470 470
This group describes the tools for importing and exporting graphs 
471 471
and graph related data. Now it supports the LEMON format, the
472 472
\c DIMACS format and the encapsulated postscript (EPS) format.
473 473
*/
474 474

	
475 475
/**
476 476
@defgroup lemon_io Lemon Input-Output
477 477
@ingroup io_group
478
\brief Reading and writing LEMON format
478
\brief Reading and writing \ref lgf-format "Lemon Graph Format".
479 479

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

	
485 483
/**
486 484
@defgroup eps_io Postscript exporting
487 485
@ingroup io_group
488 486
\brief General \c EPS drawer and graph exporter
489 487

	
490 488
This group describes general \c EPS drawing methods and special
491 489
graph exporting tools. 
492 490
*/
493 491

	
494 492

	
495 493
/**
496 494
@defgroup concept Concepts
497 495
\brief Skeleton classes and concept checking classes
498 496

	
499 497
This group describes the data/algorithm skeletons and concept checking
500 498
classes implemented in LEMON.
501 499

	
502 500
The purpose of the classes in this group is fourfold.
503 501
 
504 502
- These classes contain the documentations of the concepts. In order
505 503
  to avoid document multiplications, an implementation of a concept
506 504
  simply refers to the corresponding concept class.
507 505

	
508 506
- These classes declare every functions, <tt>typedef</tt>s etc. an
509 507
  implementation of the concepts should provide, however completely
510 508
  without implementations and real data structures behind the
511 509
  interface. On the other hand they should provide nothing else. All
512 510
  the algorithms working on a data structure meeting a certain concept
513 511
  should compile with these classes. (Though it will not run properly,
514 512
  of course.) In this way it is easily to check if an algorithm
515 513
  doesn't use any extra feature of a certain implementation.
516 514

	
517 515
- The concept descriptor classes also provide a <em>checker class</em>
518 516
  that makes it possible to check whether a certain implementation of a
519 517
  concept indeed provides all the required features.
520 518

	
521 519
- Finally, They can serve as a skeleton of a new implementation of a concept.
522 520

	
523 521
*/
524 522

	
525 523

	
526 524
/**
527 525
@defgroup graph_concepts Graph Structure Concepts
528 526
@ingroup concept
529 527
\brief Skeleton and concept checking classes for graph structures
530 528

	
531 529
This group describes the skeletons and concept checking classes of LEMON's
532 530
graph structures and helper classes used to implement these.
533 531
*/
534 532

	
535 533
/* --- Unused group
536 534
@defgroup experimental Experimental Structures and Algorithms
537 535
This group describes some Experimental structures and algorithms.
538 536
The stuff here is subject to change.
539 537
*/
540 538

	
541 539
/**
542 540
\anchor demoprograms
543 541

	
544 542
@defgroup demos Demo programs
545 543

	
546 544
Some demo programs are listed here. Their full source codes can be found in
547 545
the \c demo subdirectory of the source tree.
548 546

	
549 547
It order to compile them, use <tt>--enable-demo</tt> configure option when
550 548
build the library.
551 549
*/
552 550

	
553 551
/**
554 552
@defgroup tools Standalone utility applications
555 553

	
556 554
Some utility applications are listed here. 
557 555

	
558 556
The standard compilation procedure (<tt>./configure;make</tt>) will compile
559 557
them, as well. 
560 558
*/
561 559

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

	
19 19
namespace lemon {
20 20
/*!
21 21

	
22 22

	
23 23

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

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

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

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

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

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

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

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

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

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

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

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

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

	
96 96
*/
97 97
}
98 98

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

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

	
23 23

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

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

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

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

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

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

	
42 42
namespace lemon {
43 43

	
44 44
  namespace _reader_bits {
45 45

	
46 46
    template <typename Value>
47 47
    struct DefaultConverter {
48 48
      Value operator()(const std::string& str) {
49 49
	std::istringstream is(str);
50 50
	Value value;
51 51
	is >> value;
52 52

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

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

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

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

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

	
79 79
    };
80 80

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
459 459

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

	
463 463
    Digraph& _digraph;
464 464

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

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

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

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

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

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

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

	
495 495
  public:
496 496

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

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

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

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

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

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

	
545 545
    }
546 546

	
547 547
  private:
548 548

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

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

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

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

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

	
575 575
    }
576 576

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

	
579 579
  public:
580 580

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

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

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

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

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

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

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

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

	
684 684
    /// @}
685 685

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

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

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

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

	
713 713
    /// @}
714 714

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

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

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

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

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

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

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

	
810 809
    /// @}
811 810

	
812 811
  private:
813 812

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

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

	
839 838
    void readNodes() {
840 839

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

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

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

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

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

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

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

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

	
932 931
    void readArcs() {
933 932

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

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

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

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

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

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

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

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

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

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

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

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

	
1053 1052
    void readAttributes() {
1054 1053

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

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

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

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

	
1101 1100
  public:
1102 1101

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

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

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

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

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

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

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

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

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

	
1172 1171
    }
1173 1172

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

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

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

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

	
1200 1208
  template <typename Graph>
1201 1209
  class GraphReader;
1202 1210

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

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

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

	
1212 1220
  /// \ingroup lemon_io
1213 1221
  ///  
1214
  /// \brief LGF reader for undirected graphs
1222
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
1215 1223
  ///
1216 1224
  /// This utility reads an \ref lgf-format "LGF" file.
1225
  ///
1226
  /// It can be used almost the same way as \c DigraphReader.
1227
  /// The only difference is that this class can handle edges and
1228
  /// edge maps as well as arcs and arc maps.
1217 1229
  template <typename _Graph>
1218 1230
  class GraphReader {
1219 1231
  public:
1220 1232

	
1221 1233
    typedef _Graph Graph;
1222 1234
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1223 1235
    
1224 1236
  private:
1225 1237

	
1226 1238
    std::istream* _is;
1227 1239
    bool local_is;
1228 1240

	
1229 1241
    Graph& _graph;
1230 1242

	
1231 1243
    std::string _nodes_caption;
1232 1244
    std::string _edges_caption;
1233 1245
    std::string _attributes_caption;
1234 1246

	
1235 1247
    typedef std::map<std::string, Node> NodeIndex;
1236 1248
    NodeIndex _node_index;
1237 1249
    typedef std::map<std::string, Edge> EdgeIndex;
1238 1250
    EdgeIndex _edge_index;
1239 1251
    
1240 1252
    typedef std::vector<std::pair<std::string, 
1241 1253
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1242 1254
    NodeMaps _node_maps; 
1243 1255

	
1244 1256
    typedef std::vector<std::pair<std::string,
1245 1257
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1246 1258
    EdgeMaps _edge_maps;
1247 1259

	
1248 1260
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1249 1261
      Attributes;
1250 1262
    Attributes _attributes;
1251 1263

	
1252 1264
    bool _use_nodes;
1253 1265
    bool _use_edges;
1254 1266

	
1255 1267
    bool _skip_nodes;
1256 1268
    bool _skip_edges;
1257 1269

	
1258 1270
    int line_num;
1259 1271
    std::istringstream line;
1260 1272

	
1261 1273
  public:
1262 1274

	
1263 1275
    /// \brief Constructor
1264 1276
    ///
1265
    /// Construct a undirected graph reader, which reads from the given
1277
    /// Construct an undirected graph reader, which reads from the given
1266 1278
    /// input stream.
1267 1279
    GraphReader(std::istream& is, Graph& graph) 
1268 1280
      : _is(&is), local_is(false), _graph(graph),
1269 1281
	_use_nodes(false), _use_edges(false),
1270 1282
	_skip_nodes(false), _skip_edges(false) {}
1271 1283

	
1272 1284
    /// \brief Constructor
1273 1285
    ///
1274
    /// Construct a undirected graph reader, which reads from the given
1286
    /// Construct an undirected graph reader, which reads from the given
1275 1287
    /// file.
1276 1288
    GraphReader(const std::string& fn, Graph& graph) 
1277 1289
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1278 1290
    	_use_nodes(false), _use_edges(false),
1279 1291
	_skip_nodes(false), _skip_edges(false) {}
1280 1292
    
1281 1293
    /// \brief Constructor
1282 1294
    ///
1283
    /// Construct a undirected graph reader, which reads from the given
1295
    /// Construct an undirected graph reader, which reads from the given
1284 1296
    /// file.
1285 1297
    GraphReader(const char* fn, Graph& graph) 
1286 1298
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1287 1299
    	_use_nodes(false), _use_edges(false),
1288 1300
	_skip_nodes(false), _skip_edges(false) {}
1289 1301

	
1290 1302
    /// \brief Destructor
1291 1303
    ~GraphReader() {
1292 1304
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1293 1305
	   it != _node_maps.end(); ++it) {
1294 1306
	delete it->second;
1295 1307
      }
1296 1308

	
1297 1309
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1298 1310
	   it != _edge_maps.end(); ++it) {
1299 1311
	delete it->second;
1300 1312
      }
1301 1313

	
1302 1314
      for (typename Attributes::iterator it = _attributes.begin(); 
1303 1315
	   it != _attributes.end(); ++it) {
1304 1316
	delete it->second;
1305 1317
      }
1306 1318

	
1307 1319
      if (local_is) {
1308 1320
	delete _is;
1309 1321
      }
1310 1322

	
1311 1323
    }
1312 1324

	
1313 1325
  private:
1314 1326
    friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph);    
1315 1327
    friend GraphReader<Graph> graphReader<>(const std::string& fn, 
1316 1328
					    Graph& graph);   
1317 1329
    friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph);    
1318 1330

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

	
1324 1336
      other._is = 0;
1325 1337
      other.local_is = false;
1326 1338
      
1327 1339
      _node_index.swap(other._node_index);
1328 1340
      _edge_index.swap(other._edge_index);
1329 1341

	
1330 1342
      _node_maps.swap(other._node_maps);
1331 1343
      _edge_maps.swap(other._edge_maps);
1332 1344
      _attributes.swap(other._attributes);
1333 1345

	
1334 1346
      _nodes_caption = other._nodes_caption;
1335 1347
      _edges_caption = other._edges_caption;
1336 1348
      _attributes_caption = other._attributes_caption;
1337 1349

	
1338 1350
    }
1339 1351

	
1340 1352
    GraphReader& operator=(const GraphReader&);
1341 1353

	
1342 1354
  public:
1343 1355

	
1344 1356
    /// \name Reading rules
1345 1357
    /// @{
1346 1358
    
1347 1359
    /// \brief Node map reading rule
1348 1360
    ///
1349 1361
    /// Add a node map reading rule to the reader.
1350 1362
    template <typename Map>
1351 1363
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1352 1364
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1353 1365
      _reader_bits::MapStorageBase<Node>* storage = 
1354 1366
	new _reader_bits::MapStorage<Node, Map>(map);
1355 1367
      _node_maps.push_back(std::make_pair(caption, storage));
1356 1368
      return *this;
1357 1369
    }
1358 1370

	
1359 1371
    /// \brief Node map reading rule
1360 1372
    ///
1361 1373
    /// Add a node map reading rule with specialized converter to the
1362 1374
    /// reader.
1363 1375
    template <typename Map, typename Converter>
1364 1376
    GraphReader& nodeMap(const std::string& caption, Map& map, 
1365 1377
			   const Converter& converter = Converter()) {
1366 1378
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1367 1379
      _reader_bits::MapStorageBase<Node>* storage = 
1368 1380
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1369 1381
      _node_maps.push_back(std::make_pair(caption, storage));
1370 1382
      return *this;
1371 1383
    }
1372 1384

	
1373 1385
    /// \brief Edge map reading rule
1374 1386
    ///
1375 1387
    /// Add an edge map reading rule to the reader.
1376 1388
    template <typename Map>
1377 1389
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1378 1390
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1379 1391
      _reader_bits::MapStorageBase<Edge>* storage = 
1380 1392
	new _reader_bits::MapStorage<Edge, Map>(map);
1381 1393
      _edge_maps.push_back(std::make_pair(caption, storage));
1382 1394
      return *this;
1383 1395
    }
1384 1396

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

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

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

	
1433 1445
    /// \brief Attribute reading rule
1434 1446
    ///
1435 1447
    /// Add an attribute reading rule to the reader.
1436 1448
    template <typename Value>
1437 1449
    GraphReader& attribute(const std::string& caption, Value& value) {
1438 1450
      _reader_bits::ValueStorageBase* storage = 
1439 1451
	new _reader_bits::ValueStorage<Value>(value);
1440 1452
      _attributes.insert(std::make_pair(caption, storage));
1441 1453
      return *this;
1442 1454
    }
1443 1455

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

	
1457 1469
    /// \brief Node reading rule
1458 1470
    ///
1459 1471
    /// Add a node reading rule to reader.
1460 1472
    GraphReader& node(const std::string& caption, Node& node) {
1461 1473
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1462 1474
      Converter converter(_node_index);
1463 1475
      _reader_bits::ValueStorageBase* storage = 
1464 1476
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1465 1477
      _attributes.insert(std::make_pair(caption, storage));
1466 1478
      return *this;
1467 1479
    }
1468 1480

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

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

	
1493 1505
    /// @}
1494 1506

	
1495 1507
    /// \name Select section by name
1496 1508
    /// @{
1497 1509

	
1498 1510
    /// \brief Set \c \@nodes section to be read
1499 1511
    ///
1500
    /// Set \c \@nodes section to be read
1512
    /// Set \c \@nodes section to be read.
1501 1513
    GraphReader& nodes(const std::string& caption) {
1502 1514
      _nodes_caption = caption;
1503 1515
      return *this;
1504 1516
    }
1505 1517

	
1506 1518
    /// \brief Set \c \@edges section to be read
1507 1519
    ///
1508
    /// Set \c \@edges section to be read
1520
    /// Set \c \@edges section to be read.
1509 1521
    GraphReader& edges(const std::string& caption) {
1510 1522
      _edges_caption = caption;
1511 1523
      return *this;
1512 1524
    }
1513 1525

	
1514 1526
    /// \brief Set \c \@attributes section to be read
1515 1527
    ///
1516
    /// Set \c \@attributes section to be read
1528
    /// Set \c \@attributes section to be read.
1517 1529
    GraphReader& attributes(const std::string& caption) {
1518 1530
      _attributes_caption = caption;
1519 1531
      return *this;
1520 1532
    }
1521 1533

	
1522 1534
    /// @}
1523 1535

	
1524 1536
    /// \name Using previously constructed node or edge set
1525 1537
    /// @{
1526 1538

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

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

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

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

	
1593
    /// \brief Skips the reading of node section
1605
    /// \brief Skip the reading of node section
1594 1606
    ///
1595 1607
    /// Omit the reading of the node section. This implies that each node
1596
    /// map reading rule will be abanoned, and the nodes of the graph
1608
    /// map reading rule will be abandoned, and the nodes of the graph
1597 1609
    /// will not be constructed, which usually cause that the edge set
1598 1610
    /// could not be read due to lack of node name
1599
    /// resolving. Therefore, the \c skipEdges() should be used too, or
1600
    /// the useNodes() member function should be used to specify the
1601
    /// label of the nodes.
1611
    /// could not be read due to lack of node name resolving.
1612
    /// Therefore \c skipEdges() function should also be used, or
1613
    /// \c useNodes() should be used to specify the label of the nodes.
1602 1614
    GraphReader& skipNodes() {
1603 1615
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
1604 1616
      _skip_nodes = true;
1605 1617
      return *this;
1606 1618
    }
1607 1619

	
1608
    /// \brief Skips the reading of edge section
1620
    /// \brief Skip the reading of edge section
1609 1621
    ///
1610 1622
    /// Omit the reading of the edge section. This implies that each edge
1611
    /// map reading rule will be abanoned, and the edges of the graph
1623
    /// map reading rule will be abandoned, and the edges of the graph
1612 1624
    /// will not be constructed.
1613 1625
    GraphReader& skipEdges() {
1614 1626
      LEMON_ASSERT(!_skip_edges, "Skip edges already set"); 
1615 1627
      _skip_edges = true;
1616 1628
      return *this;
1617 1629
    }
1618 1630

	
1619 1631
    /// @}
1620 1632

	
1621 1633
  private:
1622 1634

	
1623 1635
    bool readLine() {
1624 1636
      std::string str;
1625 1637
      while(++line_num, std::getline(*_is, str)) {
1626 1638
	line.clear(); line.str(str);
1627 1639
	char c;
1628 1640
	if (line >> std::ws >> c && c != '#') {
1629 1641
	  line.putback(c);
1630 1642
	  return true;
1631 1643
	}
1632 1644
      }
1633 1645
      return false;
1634 1646
    }
1635 1647

	
1636 1648
    bool readSuccess() {
1637 1649
      return static_cast<bool>(*_is);
1638 1650
    }
1639 1651
    
1640 1652
    void skipSection() {
1641 1653
      char c;
1642 1654
      while (readSuccess() && line >> c && c != '@') {
1643 1655
	readLine();
1644 1656
      }
1645 1657
      line.putback(c);
1646 1658
    }
1647 1659

	
1648 1660
    void readNodes() {
1649 1661

	
1650 1662
      std::vector<int> map_index(_node_maps.size());
1651 1663
      int map_num, label_index;
1652 1664

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

	
1688 1700
	{
1689 1701
	  std::map<std::string, int>::iterator jt = maps.find("label");
1690 1702
	  if (jt != maps.end()) {
1691 1703
	    label_index = jt->second;
1692 1704
	  } else {
1693 1705
	    label_index = -1;
1694 1706
	  }
1695 1707
	}
1696 1708
	map_num = maps.size();
1697 1709
      }
1698 1710

	
1699 1711
      while (readLine() && line >> c && c != '@') {
1700 1712
	line.putback(c);
1701 1713

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

	
1731 1743
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1732 1744
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
1733 1745
	}
1734 1746

	
1735 1747
      }
1736 1748
      if (readSuccess()) {
1737 1749
	line.putback(c);
1738 1750
      }
1739 1751
    }
1740 1752

	
1741 1753
    void readEdges() {
1742 1754

	
1743 1755
      std::vector<int> map_index(_edge_maps.size());
1744 1756
      int map_num, label_index;
1745 1757

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

	
1781 1793
	{
1782 1794
	  std::map<std::string, int>::iterator jt = maps.find("label");
1783 1795
	  if (jt != maps.end()) {
1784 1796
	    label_index = jt->second;
1785 1797
	  } else {
1786 1798
	    label_index = -1;
1787 1799
	  }
1788 1800
	}
1789 1801
	map_num = maps.size();
1790 1802
      }
1791 1803

	
1792 1804
      while (readLine() && line >> c && c != '@') {
1793 1805
	line.putback(c);
1794 1806

	
1795 1807
	std::string source_token;
1796 1808
	std::string target_token;
1797 1809

	
1798 1810
	if (!_reader_bits::readToken(line, source_token))
1799 1811
	  throw DataFormatError("Node u not found");
1800 1812

	
1801 1813
	if (!_reader_bits::readToken(line, target_token))
1802 1814
	  throw DataFormatError("Node v not found");
1803 1815
	
1804 1816
	std::vector<std::string> tokens(map_num);
1805 1817
	for (int i = 0; i < map_num; ++i) {
1806 1818
	  if (!_reader_bits::readToken(line, tokens[i])) {
1807 1819
	    std::ostringstream msg;
1808 1820
	    msg << "Column not found (" << i + 1 << ")";
1809 1821
	    throw DataFormatError(msg.str().c_str());
1810 1822
	  }
1811 1823
	}
1812 1824
	if (line >> std::ws >> c)
1813 1825
	  throw DataFormatError("Extra character on the end of line");
1814 1826
	
1815 1827
	Edge e;
1816 1828
	if (!_use_edges) {
1817 1829

	
1818 1830
          typename NodeIndex::iterator it;
1819 1831
 
1820 1832
          it = _node_index.find(source_token);
1821 1833
          if (it == _node_index.end()) {
1822 1834
            std::ostringstream msg;
1823 1835
            msg << "Item not found: " << source_token;
1824 1836
            throw DataFormatError(msg.str().c_str());
1825 1837
          }
1826 1838
          Node source = it->second;
1827 1839

	
1828 1840
          it = _node_index.find(target_token);
1829 1841
          if (it == _node_index.end()) {       
1830 1842
            std::ostringstream msg;            
1831 1843
            msg << "Item not found: " << target_token;
1832 1844
            throw DataFormatError(msg.str().c_str());
1833 1845
          }                                          
1834 1846
          Node target = it->second;                            
1835 1847

	
1836 1848
	  e = _graph.addEdge(source, target);
1837 1849
	  if (label_index != -1) 
1838 1850
	    _edge_index.insert(std::make_pair(tokens[label_index], e));
1839 1851
	} else {
1840 1852
	  if (label_index == -1) 
1841 1853
	    throw DataFormatError("Label map not found in file");
1842 1854
	  typename std::map<std::string, Edge>::iterator it =
1843 1855
	    _edge_index.find(tokens[label_index]);
1844 1856
	  if (it == _edge_index.end()) {
1845 1857
	    std::ostringstream msg;
1846 1858
	    msg << "Edge with label not found: " << tokens[label_index];
1847 1859
	    throw DataFormatError(msg.str().c_str());	    
1848 1860
	  }
1849 1861
	  e = it->second;
1850 1862
	}
1851 1863

	
1852 1864
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1853 1865
	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
1854 1866
	}
1855 1867

	
1856 1868
      }
1857 1869
      if (readSuccess()) {
1858 1870
	line.putback(c);
1859 1871
      }
1860 1872
    }
1861 1873

	
1862 1874
    void readAttributes() {
1863 1875

	
1864 1876
      std::set<std::string> read_attr;
1865 1877

	
1866 1878
      char c;
1867 1879
      while (readLine() && line >> c && c != '@') {
1868 1880
	line.putback(c);
1869 1881
	
1870 1882
	std::string attr, token;
1871 1883
	if (!_reader_bits::readToken(line, attr))
1872 1884
	  throw DataFormatError("Attribute name not found");
1873 1885
	if (!_reader_bits::readToken(line, token))
1874 1886
	  throw DataFormatError("Attribute value not found");
1875 1887
	if (line >> c)
1876 1888
	  throw DataFormatError("Extra character on the end of line");	  
1877 1889

	
1878 1890
	{
1879 1891
	  std::set<std::string>::iterator it = read_attr.find(attr);
1880 1892
	  if (it != read_attr.end()) {
1881 1893
	    std::ostringstream msg;
1882 1894
	    msg << "Multiple occurence of attribute " << attr;
1883 1895
	    throw DataFormatError(msg.str().c_str());
1884 1896
	  }
1885 1897
	  read_attr.insert(attr);
1886 1898
	}
1887 1899
	
1888 1900
	{
1889 1901
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1890 1902
	  while (it != _attributes.end() && it->first == attr) {
1891 1903
	    it->second->set(token);
1892 1904
	    ++it;
1893 1905
	  }
1894 1906
	}
1895 1907

	
1896 1908
      }
1897 1909
      if (readSuccess()) {
1898 1910
	line.putback(c);
1899 1911
      }
1900 1912
      for (typename Attributes::iterator it = _attributes.begin();
1901 1913
	   it != _attributes.end(); ++it) {
1902 1914
	if (read_attr.find(it->first) == read_attr.end()) {
1903 1915
	  std::ostringstream msg;
1904 1916
	  msg << "Attribute not found in file: " << it->first;
1905 1917
	  throw DataFormatError(msg.str().c_str());
1906 1918
	}	
1907 1919
      }
1908 1920
    }
1909 1921

	
1910 1922
  public:
1911 1923

	
1912 1924
    /// \name Execution of the reader    
1913 1925
    /// @{
1914 1926

	
1915 1927
    /// \brief Start the batch processing
1916 1928
    ///
1917 1929
    /// This function starts the batch processing
1918 1930
    void run() {
1919 1931
      
1920 1932
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1921 1933
      
1922 1934
      bool nodes_done = _skip_nodes;
1923 1935
      bool edges_done = _skip_edges;
1924 1936
      bool attributes_done = false;
1925 1937

	
1926 1938
      line_num = 0;      
1927 1939
      readLine();
1928 1940
      skipSection();
1929 1941

	
1930 1942
      while (readSuccess()) {
1931 1943
	try {
1932 1944
	  char c;
1933 1945
	  std::string section, caption;
1934 1946
	  line >> c;
1935 1947
	  _reader_bits::readToken(line, section);
1936 1948
	  _reader_bits::readToken(line, caption);
1937 1949

	
1938 1950
	  if (line >> c) 
1939 1951
	    throw DataFormatError("Extra character on the end of line");
1940 1952

	
1941 1953
	  if (section == "nodes" && !nodes_done) {
1942 1954
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1943 1955
	      readNodes();
1944 1956
	      nodes_done = true;
1945 1957
	    }
1946 1958
	  } else if ((section == "edges" || section == "arcs") && 
1947 1959
		     !edges_done) {
1948 1960
	    if (_edges_caption.empty() || _edges_caption == caption) {
1949 1961
	      readEdges();
1950 1962
	      edges_done = true;
1951 1963
	    }
1952 1964
	  } else if (section == "attributes" && !attributes_done) {
1953 1965
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1954 1966
	      readAttributes();
1955 1967
	      attributes_done = true;
1956 1968
	    }
1957 1969
	  } else {
1958 1970
	    readLine();
1959 1971
	    skipSection();
1960 1972
	  }
1961 1973
	} catch (DataFormatError& error) {
1962 1974
	  error.line(line_num);
1963 1975
	  throw;
1964 1976
	}	
1965 1977
      }
1966 1978

	
1967 1979
      if (!nodes_done) {
1968 1980
	throw DataFormatError("Section @nodes not found");
1969 1981
      }
1970 1982

	
1971 1983
      if (!edges_done) {
1972 1984
	throw DataFormatError("Section @edges not found");
1973 1985
      }
1974 1986

	
1975 1987
      if (!attributes_done && !_attributes.empty()) {
1976 1988
	throw DataFormatError("Section @attributes not found");
1977 1989
      }
1978 1990

	
1979 1991
    }
1980 1992

	
1981 1993
    /// @}
1982 1994
    
1983 1995
  };
1984 1996

	
1997
  /// \brief Return a \ref GraphReader class
1998
  /// 
1999
  /// This function just returns a \ref GraphReader class.
1985 2000
  /// \relates GraphReader
1986 2001
  template <typename Graph>
1987 2002
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
1988 2003
    GraphReader<Graph> tmp(is, graph);
1989 2004
    return tmp;
1990 2005
  }
1991 2006

	
2007
  /// \brief Return a \ref GraphReader class
2008
  /// 
2009
  /// This function just returns a \ref GraphReader class.
1992 2010
  /// \relates GraphReader
1993 2011
  template <typename Graph>
1994 2012
  GraphReader<Graph> graphReader(const std::string& fn, 
1995 2013
				       Graph& graph) {
1996 2014
    GraphReader<Graph> tmp(fn, graph);
1997 2015
    return tmp;
1998 2016
  }
1999 2017

	
2018
  /// \brief Return a \ref GraphReader class
2019
  /// 
2020
  /// This function just returns a \ref GraphReader class.
2000 2021
  /// \relates GraphReader
2001 2022
  template <typename Graph>
2002 2023
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
2003 2024
    GraphReader<Graph> tmp(fn, graph);
2004 2025
    return tmp;
2005 2026
  }
2006 2027

	
2007 2028
  class SectionReader;
2008 2029

	
2009 2030
  SectionReader sectionReader(std::istream& is);
2010 2031
  SectionReader sectionReader(const std::string& fn);
2011 2032
  SectionReader sectionReader(const char* fn);
2012 2033
  
2034
  /// \ingroup lemon_io
2035
  ///
2013 2036
  /// \brief Section reader class
2014 2037
  ///
2015
  /// In the \e LGF file extra sections can be placed, which contain
2016
  /// any data in arbitrary format. Such sections can be read with
2017
  /// this class. A reading rule can be added with two different
2018
  /// functions, with the \c sectionLines() function a functor can
2019
  /// process the section line-by-line. While with the \c
2038
  /// In the \ref lgf-format "LGF" file extra sections can be placed, 
2039
  /// which contain any data in arbitrary format. Such sections can be
2040
  /// read with this class. A reading rule can be added to the class 
2041
  /// with two different functions. With the \c sectionLines() function a
2042
  /// functor can process the section line-by-line, while with the \c
2020 2043
  /// sectionStream() member the section can be read from an input
2021 2044
  /// stream.
2022 2045
  class SectionReader {
2023 2046
  private:
2024 2047
    
2025 2048
    std::istream* _is;
2026 2049
    bool local_is;
2027 2050

	
2028 2051
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2029 2052
    Sections _sections;
2030 2053

	
2031 2054
    int line_num;
2032 2055
    std::istringstream line;
2033 2056

	
2034 2057
  public:
2035 2058

	
2036 2059
    /// \brief Constructor
2037 2060
    ///
2038 2061
    /// Construct a section reader, which reads from the given input
2039 2062
    /// stream.
2040 2063
    SectionReader(std::istream& is) 
2041 2064
      : _is(&is), local_is(false) {}
2042 2065

	
2043 2066
    /// \brief Constructor
2044 2067
    ///
2045 2068
    /// Construct a section reader, which reads from the given file.
2046 2069
    SectionReader(const std::string& fn) 
2047 2070
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2048 2071
    
2049 2072
    /// \brief Constructor
2050 2073
    ///
2051 2074
    /// Construct a section reader, which reads from the given file.
2052 2075
    SectionReader(const char* fn) 
2053 2076
      : _is(new std::ifstream(fn)), local_is(true) {}
2054 2077

	
2055 2078
    /// \brief Destructor
2056 2079
    ~SectionReader() {
2057 2080
      for (Sections::iterator it = _sections.begin(); 
2058 2081
	   it != _sections.end(); ++it) {
2059 2082
	delete it->second;
2060 2083
      }
2061 2084

	
2062 2085
      if (local_is) {
2063 2086
	delete _is;
2064 2087
      }
2065 2088

	
2066 2089
    }
2067 2090

	
2068 2091
  private:
2069 2092

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

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

	
2077 2100
      other._is = 0;
2078 2101
      other.local_is = false;
2079 2102
      
2080 2103
      _sections.swap(other._sections);
2081 2104
    }
2082 2105
    
2083 2106
    SectionReader& operator=(const SectionReader&);
2084 2107

	
2085 2108
  public:
2086 2109

	
2087 2110
    /// \name Section readers
2088 2111
    /// @{
2089 2112

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

	
2134 2157

	
2135 2158
    /// \brief Add a section processor with stream oriented reading
2136 2159
    ///
2137 2160
    /// The first parameter is the type of the section, the second is
2138
    /// a functor, which takes an \c std::istream& and an int&
2161
    /// a functor, which takes an \c std::istream& and an \c int&
2139 2162
    /// parameter, the latter regard to the line number of stream. The
2140 2163
    /// functor can read the input while the section go on, and the
2141 2164
    /// line number should be modified accordingly.
2142 2165
    template <typename Functor>
2143 2166
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2144
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
2167
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2145 2168
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2146 2169
		   "Multiple reading of section.");
2147 2170
      _sections.insert(std::make_pair(type, 
2148 2171
	 new _reader_bits::StreamSection<Functor>(functor)));
2149 2172
      return *this;
2150 2173
    }    
2151 2174
    
2152 2175
    /// @}
2153 2176

	
2154 2177
  private:
2155 2178

	
2156 2179
    bool readLine() {
2157 2180
      std::string str;
2158 2181
      while(++line_num, std::getline(*_is, str)) {
2159 2182
	line.clear(); line.str(str);
2160 2183
	char c;
2161 2184
	if (line >> std::ws >> c && c != '#') {
2162 2185
	  line.putback(c);
2163 2186
	  return true;
2164 2187
	}
2165 2188
      }
2166 2189
      return false;
2167 2190
    }
2168 2191

	
2169 2192
    bool readSuccess() {
2170 2193
      return static_cast<bool>(*_is);
2171 2194
    }
2172 2195
    
2173 2196
    void skipSection() {
2174 2197
      char c;
2175 2198
      while (readSuccess() && line >> c && c != '@') {
2176 2199
	readLine();
2177 2200
      }
2178 2201
      line.putback(c);
2179 2202
    }
2180 2203

	
2181 2204
  public:
2182 2205

	
2183 2206

	
2184 2207
    /// \name Execution of the reader    
2185 2208
    /// @{
2186 2209

	
2187 2210
    /// \brief Start the batch processing
2188 2211
    ///
2189
    /// This function starts the batch processing
2212
    /// This function starts the batch processing.
2190 2213
    void run() {
2191 2214
      
2192 2215
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2193 2216
      
2194 2217
      std::set<std::string> extra_sections;
2195 2218

	
2196 2219
      line_num = 0;      
2197 2220
      readLine();
2198 2221
      skipSection();
2199 2222

	
2200 2223
      while (readSuccess()) {
2201 2224
	try {
2202 2225
	  char c;
2203 2226
	  std::string section, caption;
2204 2227
	  line >> c;
2205 2228
	  _reader_bits::readToken(line, section);
2206 2229
	  _reader_bits::readToken(line, caption);
2207 2230

	
2208 2231
	  if (line >> c) 
2209 2232
	    throw DataFormatError("Extra character on the end of line");
2210 2233

	
2211 2234
	  if (extra_sections.find(section) != extra_sections.end()) {
2212 2235
	    std::ostringstream msg;
2213 2236
	    msg << "Multiple occurence of section " << section;
2214 2237
	    throw DataFormatError(msg.str().c_str());
2215 2238
	  }
2216 2239
	  Sections::iterator it = _sections.find(section);
2217 2240
	  if (it != _sections.end()) {
2218 2241
	    extra_sections.insert(section);
2219 2242
	    it->second->process(*_is, line_num);
2220 2243
	  }
2221 2244
	  readLine();
2222 2245
	  skipSection();
2223 2246
	} catch (DataFormatError& error) {
2224 2247
	  error.line(line_num);
2225 2248
	  throw;
2226 2249
	}	
2227 2250
      }
2228 2251
      for (Sections::iterator it = _sections.begin();
2229 2252
	   it != _sections.end(); ++it) {
2230 2253
	if (extra_sections.find(it->first) == extra_sections.end()) {
2231 2254
	  std::ostringstream os;
2232 2255
	  os << "Cannot find section: " << it->first;
2233 2256
	  throw DataFormatError(os.str().c_str());
2234 2257
	}
2235 2258
      }
2236 2259
    }
2237 2260

	
2238 2261
    /// @}
2239 2262
        
2240 2263
  };
2241 2264

	
2265
  /// \brief Return a \ref SectionReader class
2266
  /// 
2267
  /// This function just returns a \ref SectionReader class.
2242 2268
  /// \relates SectionReader
2243 2269
  inline SectionReader sectionReader(std::istream& is) {
2244 2270
    SectionReader tmp(is);
2245 2271
    return tmp;
2246 2272
  }
2247 2273

	
2274
  /// \brief Return a \ref SectionReader class
2275
  /// 
2276
  /// This function just returns a \ref SectionReader class.
2248 2277
  /// \relates SectionReader
2249 2278
  inline SectionReader sectionReader(const std::string& fn) {
2250 2279
    SectionReader tmp(fn);
2251 2280
    return tmp;
2252 2281
  }
2253 2282

	
2283
  /// \brief Return a \ref SectionReader class
2284
  /// 
2285
  /// This function just returns a \ref SectionReader class.
2254 2286
  /// \relates SectionReader
2255 2287
  inline SectionReader sectionReader(const char* fn) {
2256 2288
    SectionReader tmp(fn);
2257 2289
    return tmp;
2258 2290
  }
2259 2291

	
2260 2292
  /// \ingroup lemon_io
2261 2293
  ///
2262 2294
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
2263 2295
  ///
2264 2296
  /// This class can be used to read the sections, the map names and
2265 2297
  /// the attributes from a file. Usually, the Lemon programs know
2266 2298
  /// that, which type of graph, which maps and which attributes
2267 2299
  /// should be read from a file, but in general tools (like glemon)
2268 2300
  /// the contents of an LGF file should be guessed somehow. This class
2269 2301
  /// reads the graph and stores the appropriate information for
2270 2302
  /// reading the graph.
2271 2303
  ///
2272
  ///\code LgfContents contents("graph.lgf"); 
2304
  ///\code 
2305
  /// LgfContents contents("graph.lgf"); 
2273 2306
  /// contents.run();
2274 2307
  ///
2275
  /// // does it contain any node section and arc section
2308
  /// // Does it contain any node section and arc section?
2276 2309
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2277
  ///   std::cerr << "Failure, cannot find graph" << std::endl;
2310
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
2278 2311
  ///   return -1;
2279 2312
  /// }
2280
  /// std::cout << "The name of the default node section : " 
2313
  /// std::cout << "The name of the default node section: " 
2281 2314
  ///           << contents.nodeSection(0) << std::endl;
2282
  /// std::cout << "The number of the arc maps : " 
2315
  /// std::cout << "The number of the arc maps: " 
2283 2316
  ///           << contents.arcMaps(0).size() << std::endl;
2284
  /// std::cout << "The name of second arc map : " 
2317
  /// std::cout << "The name of second arc map: " 
2285 2318
  ///           << contents.arcMaps(0)[1] << std::endl;
2286 2319
  ///\endcode
2287 2320
  class LgfContents {    
2288 2321
  private:
2289 2322

	
2290 2323
    std::istream* _is;
2291 2324
    bool local_is;
2292 2325

	
2293 2326
    std::vector<std::string> _node_sections;
2294 2327
    std::vector<std::string> _edge_sections;
2295 2328
    std::vector<std::string> _attribute_sections;
2296 2329
    std::vector<std::string> _extra_sections;
2297 2330

	
2298 2331
    std::vector<bool> _arc_sections;
2299 2332

	
2300 2333
    std::vector<std::vector<std::string> > _node_maps;
2301 2334
    std::vector<std::vector<std::string> > _edge_maps;
2302 2335

	
2303 2336
    std::vector<std::vector<std::string> > _attributes;
2304 2337

	
2305 2338

	
2306 2339
    int line_num;
2307 2340
    std::istringstream line;
2308 2341
    
2309 2342
  public:
2310 2343

	
2311 2344
    /// \brief Constructor
2312 2345
    ///
2313 2346
    /// Construct an \e LGF contents reader, which reads from the given
2314 2347
    /// input stream.
2315 2348
    LgfContents(std::istream& is) 
2316 2349
      : _is(&is), local_is(false) {}
2317 2350

	
2318 2351
    /// \brief Constructor
2319 2352
    ///
2320 2353
    /// Construct an \e LGF contents reader, which reads from the given
2321 2354
    /// file.
2322 2355
    LgfContents(const std::string& fn) 
2323 2356
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2324 2357

	
2325 2358
    /// \brief Constructor
2326 2359
    ///
2327 2360
    /// Construct an \e LGF contents reader, which reads from the given
2328 2361
    /// file.
2329 2362
    LgfContents(const char* fn)
2330 2363
      : _is(new std::ifstream(fn)), local_is(true) {}
2331 2364
    
2332 2365
    /// \brief Destructor
2333 2366
    ~LgfContents() {
2334 2367
      if (local_is) delete _is;
2335 2368
    }
2336 2369

	
2337 2370
  private:
2338 2371
    
2339 2372
    LgfContents(const LgfContents&);
2340 2373
    LgfContents& operator=(const LgfContents&);
2341 2374

	
2342 2375
  public:
2343 2376

	
2344 2377

	
2345 2378
    /// \name Node sections
2346 2379
    /// @{
2347 2380

	
2348 2381
    /// \brief Gives back the number of node sections in the file.
2349 2382
    ///
2350 2383
    /// Gives back the number of node sections in the file.
2351 2384
    int nodeSectionNum() const {
2352 2385
      return _node_sections.size();
2353 2386
    }
2354 2387

	
2355
    /// \brief Returns the section name at the given position. 
2388
    /// \brief Returns the node section name at the given position. 
2356 2389
    ///
2357
    /// Returns the section name at the given position. 
2390
    /// Returns the node section name at the given position. 
2358 2391
    const std::string& nodeSection(int i) const {
2359 2392
      return _node_sections[i];
2360 2393
    }
2361 2394

	
2362 2395
    /// \brief Gives back the node maps for the given section.
2363 2396
    ///
2364 2397
    /// Gives back the node maps for the given section.
2365 2398
    const std::vector<std::string>& nodeMapNames(int i) const {
2366 2399
      return _node_maps[i];
2367 2400
    }
2368 2401

	
2369 2402
    /// @}
2370 2403

	
2371 2404
    /// \name Arc/Edge sections 
2372 2405
    /// @{
2373 2406

	
2374 2407
    /// \brief Gives back the number of arc/edge sections in the file.
2375 2408
    ///
2376 2409
    /// Gives back the number of arc/edge sections in the file.
2377 2410
    /// \note It is synonym of \c edgeSectionNum().
2378 2411
    int arcSectionNum() const {
2379 2412
      return _edge_sections.size();
2380 2413
    }
2381 2414

	
2382
    /// \brief Returns the section name at the given position. 
2415
    /// \brief Returns the arc/edge section name at the given position. 
2383 2416
    ///
2384
    /// Returns the section name at the given position. 
2417
    /// Returns the arc/edge section name at the given position. 
2385 2418
    /// \note It is synonym of \c edgeSection().
2386 2419
    const std::string& arcSection(int i) const {
2387 2420
      return _edge_sections[i];
2388 2421
    }
2389 2422

	
2390 2423
    /// \brief Gives back the arc/edge maps for the given section.
2391 2424
    ///
2392 2425
    /// Gives back the arc/edge maps for the given section.
2393 2426
    /// \note It is synonym of \c edgeMapNames().
2394 2427
    const std::vector<std::string>& arcMapNames(int i) const {
2395 2428
      return _edge_maps[i];
2396 2429
    }
2397 2430

	
2398 2431
    /// @}
2399 2432

	
2400 2433
    /// \name Synonyms
2401 2434
    /// @{
2402 2435

	
2403 2436
    /// \brief Gives back the number of arc/edge sections in the file.
2404 2437
    ///
2405 2438
    /// Gives back the number of arc/edge sections in the file.
2406 2439
    /// \note It is synonym of \c arcSectionNum().
2407 2440
    int edgeSectionNum() const {
2408 2441
      return _edge_sections.size();
2409 2442
    }
2410 2443

	
2411 2444
    /// \brief Returns the section name at the given position. 
2412 2445
    ///
2413 2446
    /// Returns the section name at the given position. 
2414 2447
    /// \note It is synonym of \c arcSection().
2415 2448
    const std::string& edgeSection(int i) const {
2416 2449
      return _edge_sections[i];
2417 2450
    }
2418 2451

	
2419 2452
    /// \brief Gives back the edge maps for the given section.
2420 2453
    ///
2421 2454
    /// Gives back the edge maps for the given section.
2422 2455
    /// \note It is synonym of \c arcMapNames().
2423 2456
    const std::vector<std::string>& edgeMapNames(int i) const {
2424 2457
      return _edge_maps[i];
2425 2458
    }
2426 2459

	
2427 2460
    /// @}
2428 2461

	
2429 2462
    /// \name Attribute sections   
2430 2463
    /// @{
2431 2464

	
2432 2465
    /// \brief Gives back the number of attribute sections in the file.
2433 2466
    ///
2434 2467
    /// Gives back the number of attribute sections in the file.
2435 2468
    int attributeSectionNum() const {
2436 2469
      return _attribute_sections.size();
2437 2470
    }
2438 2471

	
2439
    /// \brief Returns the section name at the given position. 
2472
    /// \brief Returns the attribute section name at the given position. 
2440 2473
    ///
2441
    /// Returns the section name at the given position. 
2474
    /// Returns the attribute section name at the given position. 
2442 2475
    const std::string& attributeSectionNames(int i) const {
2443 2476
      return _attribute_sections[i];
2444 2477
    }
2445 2478

	
2446 2479
    /// \brief Gives back the attributes for the given section.
2447 2480
    ///
2448 2481
    /// Gives back the attributes for the given section.
2449 2482
    const std::vector<std::string>& attributes(int i) const {
2450 2483
      return _attributes[i];
2451 2484
    }
2452 2485

	
2453 2486
    /// @}
2454 2487

	
2455 2488
    /// \name Extra sections   
2456 2489
    /// @{
2457 2490

	
2458 2491
    /// \brief Gives back the number of extra sections in the file.
2459 2492
    ///
2460 2493
    /// Gives back the number of extra sections in the file.
2461 2494
    int extraSectionNum() const {
2462 2495
      return _extra_sections.size();
2463 2496
    }
2464 2497

	
2465 2498
    /// \brief Returns the extra section type at the given position. 
2466 2499
    ///
2467 2500
    /// Returns the section type at the given position. 
2468 2501
    const std::string& extraSection(int i) const {
2469 2502
      return _extra_sections[i];
2470 2503
    }
2471 2504

	
2472 2505
    /// @}
2473 2506

	
2474 2507
  private:
2475 2508

	
2476 2509
    bool readLine() {
2477 2510
      std::string str;
2478 2511
      while(++line_num, std::getline(*_is, str)) {
2479 2512
	line.clear(); line.str(str);
2480 2513
	char c;
2481 2514
	if (line >> std::ws >> c && c != '#') {
2482 2515
	  line.putback(c);
2483 2516
	  return true;
2484 2517
	}
2485 2518
      }
2486 2519
      return false;
2487 2520
    }
2488 2521

	
2489 2522
    bool readSuccess() {
2490 2523
      return static_cast<bool>(*_is);
2491 2524
    }
2492 2525

	
2493 2526
    void skipSection() {
2494 2527
      char c;
2495 2528
      while (readSuccess() && line >> c && c != '@') {
2496 2529
	readLine();
2497 2530
      }
2498 2531
      line.putback(c);
2499 2532
    }
2500 2533

	
2501 2534
    void readMaps(std::vector<std::string>& maps) {
2502 2535
      char c;
2503 2536
      if (!readLine() || !(line >> c) || c == '@') {
2504 2537
	if (readSuccess() && line) line.putback(c);
2505 2538
	return;
2506 2539
      }
2507 2540
      line.putback(c);
2508 2541
      std::string map;
2509 2542
      while (_reader_bits::readToken(line, map)) {
2510 2543
	maps.push_back(map);
2511 2544
      }
2512 2545
    }
2513 2546

	
2514 2547
    void readAttributes(std::vector<std::string>& attrs) {
2515 2548
      readLine();
2516 2549
      char c;
2517 2550
      while (readSuccess() && line >> c && c != '@') {
2518 2551
	line.putback(c);
2519 2552
	std::string attr;
2520 2553
	_reader_bits::readToken(line, attr);
2521 2554
	attrs.push_back(attr);
2522 2555
	readLine();
2523 2556
      }
2524 2557
      line.putback(c);
2525 2558
    }
2526 2559

	
2527 2560
  public:
2528 2561

	
2529 2562
    /// \name Execution of the contents reader    
2530 2563
    /// @{
2531 2564

	
2532
    /// \brief Start the reading
2565
    /// \brief Starts the reading
2533 2566
    ///
2534
    /// This function starts the reading
2567
    /// This function starts the reading.
2535 2568
    void run() {
2536 2569

	
2537 2570
      readLine();
2538 2571
      skipSection();
2539 2572

	
2540 2573
      while (readSuccess()) {
2541 2574

	
2542 2575
	char c;
2543 2576
	line >> c;
2544 2577

	
2545 2578
	std::string section, caption;
2546 2579
	_reader_bits::readToken(line, section);
2547 2580
	_reader_bits::readToken(line, caption);
2548 2581

	
2549 2582
	if (section == "nodes") {
2550 2583
	  _node_sections.push_back(caption);
2551 2584
	  _node_maps.push_back(std::vector<std::string>());
2552 2585
	  readMaps(_node_maps.back());
2553 2586
	  readLine(); skipSection();
2554 2587
	} else if (section == "arcs" || section == "edges") {
2555 2588
	  _edge_sections.push_back(caption);
2556 2589
	  _arc_sections.push_back(section == "arcs");
2557 2590
	  _edge_maps.push_back(std::vector<std::string>());
2558 2591
	  readMaps(_edge_maps.back());
2559 2592
	  readLine(); skipSection();
2560 2593
	} else if (section == "attributes") {
2561 2594
	  _attribute_sections.push_back(caption);
2562 2595
	  _attributes.push_back(std::vector<std::string>());
2563 2596
	  readAttributes(_attributes.back());
2564 2597
	} else {
2565 2598
	  _extra_sections.push_back(section);
2566 2599
	  readLine(); skipSection();
2567 2600
	}
2568 2601
      }
2569 2602
    }
2570 2603

	
2571 2604
    /// @}
2572 2605
    
2573 2606
  };
2574 2607
}
2575 2608

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

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

	
23 23

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

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

	
31 31
#include <algorithm>
32 32

	
33 33
#include <vector>
34 34
#include <functional>
35 35

	
36 36
#include <lemon/assert.h>
37 37
#include <lemon/graph_utils.h>
38 38

	
39 39
namespace lemon {
40 40

	
41 41
  namespace _writer_bits {
42 42

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
228 228
    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 307

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

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

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

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

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

	
376 376

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

	
380 380
    const Digraph& _digraph;
381 381

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

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

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

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

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

	
406 406
  public:
407 407

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

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

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

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

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

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

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

	
454 454
  private:
455 455

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

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

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

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

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

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

	
484 484
  public:
485 485

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

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

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

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

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

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

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

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

	
589
    /// \name Select section by name
589
    /// \name Section captions
590 590
    /// @{
591 591

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

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

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

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

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

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

	
637 637
    /// @}
638 638

	
639 639
  private:
640 640

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
887 896
  template <typename Graph>
888 897
  class GraphWriter;
889 898

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

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

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

	
899 908
  /// \ingroup lemon_io
900 909
  ///  
901
  /// \brief LGF writer for directed graphs
910
  /// \brief \ref lgf-format "LGF" writer for directed graphs
902 911
  ///
903 912
  /// This utility writes an \ref lgf-format "LGF" file.
913
  ///
914
  /// It can be used almost the same way as \c DigraphWriter.
915
  /// The only difference is that this class can handle edges and
916
  /// edge maps as well as arcs and arc maps.
904 917
  template <typename _Graph>
905 918
  class GraphWriter {
906 919
  public:
907 920

	
908 921
    typedef _Graph Graph;
909 922
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
910 923
    
911 924
  private:
912 925

	
913 926

	
914 927
    std::ostream* _os;
915 928
    bool local_os;
916 929

	
917 930
    Graph& _graph;
918 931

	
919 932
    std::string _nodes_caption;
920 933
    std::string _edges_caption;
921 934
    std::string _attributes_caption;
922 935
    
923 936
    typedef std::map<Node, std::string> NodeIndex;
924 937
    NodeIndex _node_index;
925 938
    typedef std::map<Edge, std::string> EdgeIndex;
926 939
    EdgeIndex _edge_index;
927 940

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

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

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

	
940 953
    bool _skip_nodes;
941 954
    bool _skip_edges;
942 955

	
943 956
  public:
944 957

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

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

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

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

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

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

	
986 999
      if (local_os) {
987 1000
	delete _os;
988 1001
      }
989 1002
    }
990 1003
    
991 1004
  private:
992 1005

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

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

	
1004 1017
      other._os = 0;
1005 1018
      other.local_os = false;
1006 1019

	
1007 1020
      _node_index.swap(other._node_index);
1008 1021
      _edge_index.swap(other._edge_index);
1009 1022

	
1010 1023
      _node_maps.swap(other._node_maps);
1011 1024
      _edge_maps.swap(other._edge_maps);
1012 1025
      _attributes.swap(other._attributes);
1013 1026

	
1014 1027
      _nodes_caption = other._nodes_caption;
1015 1028
      _edges_caption = other._edges_caption;
1016 1029
      _attributes_caption = other._attributes_caption;
1017 1030
    }
1018 1031

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

	
1021 1034
  public:
1022 1035

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

	
1038 1051
    /// \brief Node map writing rule
1039 1052
    ///
1040 1053
    /// Add a node map writing rule with specialized converter to the
1041 1054
    /// writer.
1042 1055
    template <typename Map, typename Converter>
1043 1056
    GraphWriter& nodeMap(const std::string& caption, const Map& map, 
1044 1057
			   const Converter& converter = Converter()) {
1045 1058
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1046 1059
      _writer_bits::MapStorageBase<Node>* storage = 
1047 1060
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1048 1061
      _node_maps.push_back(std::make_pair(caption, storage));
1049 1062
      return *this;
1050 1063
    }
1051 1064

	
1052 1065
    /// \brief Edge map writing rule
1053 1066
    ///
1054 1067
    /// Add an edge map writing rule to the writer.
1055 1068
    template <typename Map>
1056 1069
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1057 1070
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1058 1071
      _writer_bits::MapStorageBase<Edge>* storage = 
1059 1072
	new _writer_bits::MapStorage<Edge, Map>(map);
1060 1073
      _edge_maps.push_back(std::make_pair(caption, storage));
1061 1074
      return *this;
1062 1075
    }
1063 1076

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

	
1078 1091
    /// \brief Arc map writing rule
1079 1092
    ///
1080 1093
    /// Add an arc map writing rule to the writer.
1081 1094
    template <typename Map>
1082 1095
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1083 1096
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1084 1097
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
1085 1098
	new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1086 1099
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1087 1100
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
1088 1101
	new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1089 1102
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1090 1103
      return *this;
1091 1104
    }
1092 1105

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

	
1112 1125
    /// \brief Attribute writing rule
1113 1126
    ///
1114 1127
    /// Add an attribute writing rule to the writer.
1115 1128
    template <typename Value>
1116 1129
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1117 1130
      _writer_bits::ValueStorageBase* storage = 
1118 1131
	new _writer_bits::ValueStorage<Value>(value);
1119 1132
      _attributes.push_back(std::make_pair(caption, storage));
1120 1133
      return *this;
1121 1134
    }
1122 1135

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

	
1136 1149
    /// \brief Node writing rule
1137 1150
    ///
1138 1151
    /// Add a node writing rule to the writer.
1139 1152
    GraphWriter& node(const std::string& caption, const Node& node) {
1140 1153
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1141 1154
      Converter converter(_node_index);
1142 1155
      _writer_bits::ValueStorageBase* storage = 
1143 1156
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1144 1157
      _attributes.push_back(std::make_pair(caption, storage));
1145 1158
      return *this;
1146 1159
    }
1147 1160

	
1148 1161
    /// \brief Edge writing rule
1149 1162
    ///
1150 1163
    /// Add an edge writing rule to writer.
1151 1164
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1152 1165
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1153 1166
      Converter converter(_edge_index);
1154 1167
      _writer_bits::ValueStorageBase* storage = 
1155 1168
	new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1156 1169
      _attributes.push_back(std::make_pair(caption, storage));
1157 1170
      return *this;
1158 1171
    }
1159 1172

	
1160 1173
    /// \brief Arc writing rule
1161 1174
    ///
1162 1175
    /// Add an arc writing rule to writer.
1163 1176
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1164 1177
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1165 1178
      Converter converter(_graph, _edge_index);
1166 1179
      _writer_bits::ValueStorageBase* storage = 
1167 1180
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1168 1181
      _attributes.push_back(std::make_pair(caption, storage));
1169 1182
      return *this;
1170 1183
    }
1171 1184

	
1172
    /// \name Select section by name
1185
    /// \name Section captions
1173 1186
    /// @{
1174 1187

	
1175
    /// \brief Set \c \@nodes section to be read
1188
    /// \brief Add an additional caption to the \c \@nodes section
1176 1189
    ///
1177
    /// Set \c \@nodes section to be read
1190
    /// Add an additional caption to the \c \@nodes section.
1178 1191
    GraphWriter& nodes(const std::string& caption) {
1179 1192
      _nodes_caption = caption;
1180 1193
      return *this;
1181 1194
    }
1182 1195

	
1183
    /// \brief Set \c \@edges section to be read
1196
    /// \brief Add an additional caption to the \c \@arcs section
1184 1197
    ///
1185
    /// Set \c \@edges section to be read
1198
    /// Add an additional caption to the \c \@arcs section.
1186 1199
    GraphWriter& edges(const std::string& caption) {
1187 1200
      _edges_caption = caption;
1188 1201
      return *this;
1189 1202
    }
1190 1203

	
1191
    /// \brief Set \c \@attributes section to be read
1204
    /// \brief Add an additional caption to the \c \@attributes section
1192 1205
    ///
1193
    /// Set \c \@attributes section to be read
1206
    /// Add an additional caption to the \c \@attributes section.
1194 1207
    GraphWriter& attributes(const std::string& caption) {
1195 1208
      _attributes_caption = caption;
1196 1209
      return *this;
1197 1210
    }
1198 1211

	
1199 1212
    /// \name Skipping section
1200 1213
    /// @{
1201 1214

	
1202 1215
    /// \brief Skip writing the node set
1203 1216
    ///
1204
    /// The \c \@nodes section will be not written to the stream.
1217
    /// The \c \@nodes section will not be written to the stream.
1205 1218
    GraphWriter& skipNodes() {
1206 1219
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1207 1220
      _skip_nodes = true;
1208 1221
      return *this;
1209 1222
    }
1210 1223

	
1211 1224
    /// \brief Skip writing edge set
1212 1225
    ///
1213
    /// The \c \@edges section will be not written to the stream.
1226
    /// The \c \@edges section will not be written to the stream.
1214 1227
    GraphWriter& skipEdges() {
1215 1228
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1216 1229
      _skip_edges = true;
1217 1230
      return *this;
1218 1231
    }
1219 1232

	
1220 1233
    /// @}
1221 1234

	
1222 1235
  private:
1223 1236

	
1224 1237
    void writeNodes() {
1225 1238
      _writer_bits::MapStorageBase<Node>* label = 0;
1226 1239
      for (typename NodeMaps::iterator it = _node_maps.begin();
1227 1240
	   it != _node_maps.end(); ++it) {
1228 1241
        if (it->first == "label") {
1229 1242
	  label = it->second;
1230 1243
	  break;
1231 1244
	}
1232 1245
      }
1233 1246

	
1234 1247
      *_os << "@nodes";
1235 1248
      if (!_nodes_caption.empty()) {
1236 1249
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
1237 1250
      }
1238 1251
      *_os << std::endl;
1239 1252

	
1240 1253
      if (label == 0) {
1241 1254
	*_os << "label" << '\t';
1242 1255
      }
1243 1256
      for (typename NodeMaps::iterator it = _node_maps.begin();
1244 1257
	   it != _node_maps.end(); ++it) {
1245 1258
	_writer_bits::writeToken(*_os, it->first) << '\t';
1246 1259
      }
1247 1260
      *_os << std::endl;
1248 1261

	
1249 1262
      std::vector<Node> nodes;
1250 1263
      for (NodeIt n(_graph); n != INVALID; ++n) {
1251 1264
	nodes.push_back(n);
1252 1265
      }
1253 1266
      
1254 1267
      if (label == 0) {
1255 1268
	IdMap<Graph, Node> id_map(_graph);
1256 1269
	_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1257 1270
	std::sort(nodes.begin(), nodes.end(), id_less);
1258 1271
      } else {
1259 1272
	label->sort(nodes);
1260 1273
      }
1261 1274

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

	
1284 1297
    void createNodeIndex() {
1285 1298
      _writer_bits::MapStorageBase<Node>* label = 0;
1286 1299
      for (typename NodeMaps::iterator it = _node_maps.begin();
1287 1300
	   it != _node_maps.end(); ++it) {
1288 1301
        if (it->first == "label") {
1289 1302
	  label = it->second;
1290 1303
	  break;
1291 1304
	}
1292 1305
      }
1293 1306

	
1294 1307
      if (label == 0) {
1295 1308
	for (NodeIt n(_graph); n != INVALID; ++n) {
1296 1309
	  std::ostringstream os;
1297 1310
	  os << _graph.id(n);
1298 1311
	  _node_index.insert(std::make_pair(n, os.str()));	  
1299 1312
	}	
1300 1313
      } else {
1301 1314
	for (NodeIt n(_graph); n != INVALID; ++n) {
1302 1315
	  std::string value = label->get(n);	  
1303 1316
	  _node_index.insert(std::make_pair(n, value));
1304 1317
	}
1305 1318
      }
1306 1319
    }
1307 1320

	
1308 1321
    void writeEdges() {
1309 1322
      _writer_bits::MapStorageBase<Edge>* label = 0;
1310 1323
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1311 1324
	   it != _edge_maps.end(); ++it) {
1312 1325
        if (it->first == "label") {
1313 1326
	  label = it->second;
1314 1327
	  break;
1315 1328
	}
1316 1329
      }
1317 1330

	
1318 1331
      *_os << "@edges";
1319 1332
      if (!_edges_caption.empty()) {
1320 1333
	_writer_bits::writeToken(*_os << ' ', _edges_caption);
1321 1334
      }
1322 1335
      *_os << std::endl;
1323 1336

	
1324 1337
      *_os << '\t' << '\t';
1325 1338
      if (label == 0) {
1326 1339
	*_os << "label" << '\t';
1327 1340
      }
1328 1341
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1329 1342
	   it != _edge_maps.end(); ++it) {
1330 1343
	_writer_bits::writeToken(*_os, it->first) << '\t';
1331 1344
      }
1332 1345
      *_os << std::endl;
1333 1346

	
1334 1347
      std::vector<Edge> edges;
1335 1348
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1336 1349
	edges.push_back(n);
1337 1350
      }
1338 1351
      
1339 1352
      if (label == 0) {
1340 1353
	IdMap<Graph, Edge> id_map(_graph);
1341 1354
	_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1342 1355
	std::sort(edges.begin(), edges.end(), id_less);
1343 1356
      } else {
1344 1357
	label->sort(edges);
1345 1358
      }
1346 1359

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

	
1375 1388
    void createEdgeIndex() {
1376 1389
      _writer_bits::MapStorageBase<Edge>* label = 0;
1377 1390
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1378 1391
	   it != _edge_maps.end(); ++it) {
1379 1392
        if (it->first == "label") {
1380 1393
	  label = it->second;
1381 1394
	  break;
1382 1395
	}
1383 1396
      }
1384 1397

	
1385 1398
      if (label == 0) {
1386 1399
	for (EdgeIt e(_graph); e != INVALID; ++e) {
1387 1400
	  std::ostringstream os;
1388 1401
	  os << _graph.id(e);
1389 1402
	  _edge_index.insert(std::make_pair(e, os.str()));	  
1390 1403
	}	
1391 1404
      } else {
1392 1405
	for (EdgeIt e(_graph); e != INVALID; ++e) {
1393 1406
	  std::string value = label->get(e);	  
1394 1407
	  _edge_index.insert(std::make_pair(e, value));
1395 1408
	}
1396 1409
      }
1397 1410
    }
1398 1411

	
1399 1412
    void writeAttributes() {
1400 1413
      if (_attributes.empty()) return;
1401 1414
      *_os << "@attributes";
1402 1415
      if (!_attributes_caption.empty()) {
1403 1416
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
1404 1417
      }
1405 1418
      *_os << std::endl;
1406 1419
      for (typename Attributes::iterator it = _attributes.begin();
1407 1420
	   it != _attributes.end(); ++it) {
1408 1421
	_writer_bits::writeToken(*_os, it->first) << ' ';
1409 1422
	_writer_bits::writeToken(*_os, it->second->get());
1410 1423
	*_os << std::endl;
1411 1424
      }
1412 1425
    }
1413 1426
    
1414 1427
  public:
1415 1428
    
1416 1429
    /// \name Execution of the writer    
1417 1430
    /// @{
1418 1431

	
1419 1432
    /// \brief Start the batch processing
1420 1433
    ///
1421
    /// This function starts the batch processing
1434
    /// This function starts the batch processing.
1422 1435
    void run() {
1423 1436
      if (!_skip_nodes) {
1424 1437
	writeNodes();
1425 1438
      } else {
1426 1439
	createNodeIndex();
1427 1440
      }
1428 1441
      if (!_skip_edges) {      
1429 1442
	writeEdges();
1430 1443
      } else {
1431 1444
	createEdgeIndex();
1432 1445
      }
1433 1446
      writeAttributes();
1434 1447
    }
1435 1448

	
1436
    /// \brief Gives back the stream of the writer
1449
    /// \brief Give back the stream of the writer
1437 1450
    ///
1438
    /// Gives back the stream of the writer
1451
    /// Give back the stream of the writer
1439 1452
    std::ostream& ostream() {
1440 1453
      return *_os;
1441 1454
    }
1442 1455

	
1443 1456
    /// @}
1444 1457
  };
1445 1458

	
1459
  /// \brief Return a \ref GraphWriter class
1460
  /// 
1461
  /// This function just returns a \ref GraphWriter class.
1446 1462
  /// \relates GraphWriter
1447 1463
  template <typename Graph>
1448 1464
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph) {
1449 1465
    GraphWriter<Graph> tmp(os, graph);
1450 1466
    return tmp;
1451 1467
  }
1452 1468

	
1469
  /// \brief Return a \ref GraphWriter class
1470
  /// 
1471
  /// This function just returns a \ref GraphWriter class.
1453 1472
  /// \relates GraphWriter
1454 1473
  template <typename Graph>
1455 1474
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph) {
1456 1475
    GraphWriter<Graph> tmp(fn, graph);
1457 1476
    return tmp;
1458 1477
  }
1459 1478

	
1479
  /// \brief Return a \ref GraphWriter class
1480
  /// 
1481
  /// This function just returns a \ref GraphWriter class.
1460 1482
  /// \relates GraphWriter
1461 1483
  template <typename Graph>
1462 1484
  GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) {
1463 1485
    GraphWriter<Graph> tmp(fn, graph);
1464 1486
    return tmp;
1465 1487
  }
1466 1488
}
1467 1489

	
1468 1490
#endif
0 comments (0 inline)