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

	
19
namespace lemon {
20
/*!
21

	
22

	
23

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

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

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

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

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

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

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

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

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

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

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

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

	
93
*/
94
}
95

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

	
11 12
DOC_EPS_IMAGES18 = \
12 13
	nodeshape_0.eps \
13 14
	nodeshape_1.eps \
14 15
	nodeshape_2.eps \
15 16
	nodeshape_3.eps \
16 17
	nodeshape_4.eps
17 18

	
18 19
DOC_EPS_IMAGES = \
19 20
	$(DOC_EPS_IMAGES18)
20 21

	
21 22
DOC_PNG_IMAGES = \
22 23
	$(DOC_EPS_IMAGES:%.eps=doc/gen-images/%.png)
23 24

	
24 25
EXTRA_DIST += $(DOC_EPS_IMAGES:%=doc/images/%)
25 26

	
26 27
doc/html:
27 28
	$(MAKE) $(AM_MAKEFLAGS) html
28 29

	
29 30
GS_COMMAND=gs -dNOPAUSE -dBATCH -q -dEPSCrop -dTextAlphaBits=4 -dGraphicsAlphaBits=4
30 31

	
31 32
$(DOC_EPS_IMAGES18:%.eps=doc/gen-images/%.png): doc/gen-images/%.png: doc/images/%.eps
32 33
	-mkdir doc/gen-images
33 34
	if test ${gs_found} = yes; then \
34 35
	  $(GS_COMMAND) -sDEVICE=pngalpha -r18 -sOutputFile=$@ $<; \
35 36
	else \
36 37
	  echo; \
37 38
	  echo "Ghostscript not found."; \
38 39
	  echo; \
39 40
	  exit 1; \
40 41
	fi
41 42

	
42 43
html-local: $(DOC_PNG_IMAGES)
43 44
	if test ${doxygen_found} = yes; then \
44 45
	  cd doc; \
45 46
	  doxygen Doxyfile; \
46 47
	  cd ..; \
47 48
	else \
48 49
	  echo; \
49 50
	  echo "Doxygen not found."; \
50 51
	  echo; \
51 52
	  exit 1; \
52 53
	fi
53 54

	
54 55
clean-local:
55 56
	-rm -rf doc/html
56 57
	-rm -f doc/doxygen.log
57 58
	-rm -f $(DOC_PNG_IMAGES)
58 59
	-rm -rf doc/gen-images
59 60

	
60 61
update-external-tags:
61 62
	wget -O doc/libstdc++.tag.tmp http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag && \
62 63
	mv doc/libstdc++.tag.tmp doc/libstdc++.tag || \
63 64
	rm doc/libstdc++.tag.tmp
64 65

	
65 66
install-html-local: doc/html
66 67
	@$(NORMAL_INSTALL)
67 68
	$(mkinstalldirs) $(DESTDIR)$(htmldir)/docs
68 69
	for p in doc/html/*.{html,css,png,map,gif,tag} ; do \
69 70
	  f="`echo $$p | sed -e 's|^.*/||'`"; \
70 71
	  echo " $(INSTALL_DATA) $$p $(DESTDIR)$(htmldir)/docs/$$f"; \
71 72
	  $(INSTALL_DATA) $$p $(DESTDIR)$(htmldir)/docs/$$f; \
72 73
	done
73 74

	
74 75
uninstall-local:
75 76
	@$(NORMAL_UNINSTALL)
76 77
	for p in doc/html/*.{html,css,png,map,gif,tag} ; do \
77 78
	  f="`echo $$p | sed -e 's|^.*/||'`"; \
78 79
	  echo " rm -f $(DESTDIR)$(htmldir)/docs/$$f"; \
79 80
	  rm -f $(DESTDIR)$(htmldir)/docs/$$f; \
80 81
	done
81 82

	
82 83
.PHONY: update-external-tags
Ignore white space 6 line context
... ...
@@ -390,191 +390,172 @@
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 478
\brief Reading and writing LEMON format
479 479

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

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

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

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

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

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

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

	
513 494

	
514 495
/**
515 496
@defgroup concept Concepts
516 497
\brief Skeleton classes and concept checking classes
517 498

	
518 499
This group describes the data/algorithm skeletons and concept checking
519 500
classes implemented in LEMON.
520 501

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

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

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

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

	
542 523
*/
543 524

	
544 525

	
545 526
/**
546 527
@defgroup graph_concepts Graph Structure Concepts
547 528
@ingroup concept
548 529
\brief Skeleton and concept checking classes for graph structures
549 530

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

	
554 535
/* --- Unused group
555 536
@defgroup experimental Experimental Structures and Algorithms
556 537
This group describes some Experimental structures and algorithms.
557 538
The stuff here is subject to change.
558 539
*/
559 540

	
560 541
/**
561 542
\anchor demoprograms
562 543

	
563 544
@defgroup demos Demo programs
564 545

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

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

	
572 553
/**
573 554
@defgroup tools Standalone utility applications
574 555

	
575 556
Some utility applications are listed here. 
576 557

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

	
Ignore white space 192 line context
... ...
@@ -175,740 +175,838 @@
175 175

	
176 176
    bool isIdentifierFirstChar(char c) {
177 177
      return ('a' <= c && c <= 'z') ||
178 178
	('A' <= c && c <= 'Z') || c == '_';
179 179
    }
180 180

	
181 181
    bool isIdentifierChar(char c) {
182 182
      return isIdentifierFirstChar(c) ||
183 183
	('0' <= c && c <= '9');
184 184
    }
185 185

	
186 186
    char readEscape(std::istream& is) {
187 187
      char c;
188 188
      if (!is.get(c))
189 189
	throw DataFormatError("Escape format error");
190 190

	
191 191
      switch (c) {
192 192
      case '\\':
193 193
	return '\\';
194 194
      case '\"':
195 195
	return '\"';
196 196
      case '\'':
197 197
	return '\'';
198 198
      case '\?':
199 199
	return '\?';
200 200
      case 'a':
201 201
	return '\a';
202 202
      case 'b':
203 203
	return '\b';
204 204
      case 'f':
205 205
	return '\f';
206 206
      case 'n':
207 207
	return '\n';
208 208
      case 'r':
209 209
	return '\r';
210 210
      case 't':
211 211
	return '\t';
212 212
      case 'v':
213 213
	return '\v';
214 214
      case 'x':
215 215
	{
216 216
	  int code;
217 217
	  if (!is.get(c) || !isHex(c)) 
218 218
	    throw DataFormatError("Escape format error");
219 219
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
220 220
	  else code = code * 16 + valueHex(c);
221 221
	  return code;
222 222
	}
223 223
      default:
224 224
	{
225 225
	  int code;
226 226
	  if (!isOct(c)) 
227 227
	    throw DataFormatError("Escape format error");
228 228
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
229 229
	    is.putback(c);
230 230
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
231 231
	    is.putback(c);
232 232
	  else code = code * 8 + valueOct(c);
233 233
	  return code;
234 234
	}	      
235 235
      } 
236 236
    }
237 237
    
238 238
    std::istream& readToken(std::istream& is, std::string& str) {
239 239
      std::ostringstream os;
240 240

	
241 241
      char c;
242 242
      is >> std::ws;
243 243
      
244 244
      if (!is.get(c)) 
245 245
	return is;
246 246

	
247 247
      if (c == '\"') {
248 248
	while (is.get(c) && c != '\"') {
249 249
	  if (c == '\\') 
250 250
	    c = readEscape(is);
251 251
	  os << c;
252 252
	}
253 253
	if (!is) 
254 254
	  throw DataFormatError("Quoted format error");
255 255
      } else {
256 256
	is.putback(c);
257 257
	while (is.get(c) && !isWhiteSpace(c)) {
258 258
	  if (c == '\\') 
259 259
	    c = readEscape(is);
260 260
	  os << c;
261 261
	}
262 262
	if (!is) {
263 263
	  is.clear();
264 264
	} else {
265 265
	  is.putback(c);
266 266
	}
267 267
      }
268 268
      str = os.str();
269 269
      return is;
270 270
    }
271

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

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

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

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

	
304 327
    typedef _Digraph Digraph;
305 328
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
306 329
    
307 330
  private:
308 331

	
309 332

	
310 333
    std::istream* _is;
311 334
    bool local_is;
312 335

	
313 336
    Digraph& _digraph;
314 337

	
315 338
    std::string _nodes_caption;
316 339
    std::string _arcs_caption;
317 340
    std::string _attributes_caption;
318 341

	
319 342
    typedef std::map<std::string, Node> NodeIndex;
320 343
    NodeIndex _node_index;
321 344
    typedef std::map<std::string, Arc> ArcIndex;
322 345
    ArcIndex _arc_index;
323 346
    
324 347
    typedef std::vector<std::pair<std::string, 
325 348
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
326 349
    NodeMaps _node_maps; 
327 350

	
328 351
    typedef std::vector<std::pair<std::string,
329 352
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
330 353
    ArcMaps _arc_maps;
331 354

	
332 355
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
333 356
      Attributes;
334 357
    Attributes _attributes;
335 358

	
336 359
    bool _use_nodes;
337 360
    bool _use_arcs;
338 361

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

	
342 365
  public:
343 366

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

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

	
354

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

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

	
365 399
      other.is = 0;
366 400
      other.local_is = false;
367 401
      
368 402
      _node_index.swap(other._node_index);
369 403
      _arc_index.swap(other._arc_index);
370 404

	
371 405
      _node_maps.swap(other._node_maps);
372 406
      _arc_maps.swap(other._arc_maps);
373 407
      _attributes.swap(other._attributes);
374 408

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

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

	
387 421
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
388 422
	   it != _arc_maps.end(); ++it) {
389 423
	delete it->second;
390 424
      }
391 425

	
392 426
      for (typename Attributes::iterator it = _attributes.begin(); 
393 427
	   it != _attributes.end(); ++it) {
394 428
	delete it->second;
395 429
      }
396 430

	
397 431
      if (local_is) {
398 432
	delete _is;
399 433
      }
400 434

	
401 435
    }
402 436

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

	
407 441
  public:
408 442

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
646
    /// @}
647

	
560 648
  private:
561 649

	
562 650
    bool readLine() {
563 651
      std::string str;
564 652
      while(++line_num, std::getline(*_is, str)) {
565 653
	line.clear(); line.str(str);
566 654
	char c;
567 655
	if (line >> std::ws >> c && c != '#') {
568 656
	  line.putback(c);
569 657
	  return true;
570 658
	}
571 659
      }
572 660
      return false;
573 661
    }
574 662

	
575 663
    bool readSuccess() {
576 664
      return static_cast<bool>(*_is);
577 665
    }
578 666
    
579 667
    void skipSection() {
580 668
      char c;
581 669
      while (readSuccess() && line >> c && c != '@') {
582 670
	readLine();
583 671
      }
584 672
      line.putback(c);
585 673
    }
586 674

	
587 675
    void readNodes() {
588 676

	
589 677
      std::vector<int> map_index(_node_maps.size());
590 678
      int map_num, label_index;
591 679

	
592 680
      if (!readLine()) 
593 681
	throw DataFormatError("Cannot find map captions");
594 682
      
595 683
      {
596 684
	std::map<std::string, int> maps;
597 685
	
598 686
	std::string map;
599 687
	int index = 0;
600
	while (_reader_bits::readIdentifier(line, map)) {
688
	while (_reader_bits::readToken(line, map)) {
601 689
	  if (maps.find(map) != maps.end()) {
602 690
	    std::ostringstream msg;
603 691
	    msg << "Multiple occurence of node map: " << map;
604 692
	    throw DataFormatError(msg.str().c_str());
605 693
	  }
606 694
	  maps.insert(std::make_pair(map, index));
607 695
	  ++index;
608 696
	}
609 697
	
610 698
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
611 699
	  std::map<std::string, int>::iterator jt = 
612 700
	    maps.find(_node_maps[i].first);
613 701
	  if (jt == maps.end()) {
614 702
	    std::ostringstream msg;
615 703
	    msg << "Map not found in file: " << _node_maps[i].first;
616 704
	    throw DataFormatError(msg.str().c_str());
617 705
	  }
618 706
	  map_index[i] = jt->second;
619 707
	}
620 708

	
621 709
	{
622 710
	  std::map<std::string, int>::iterator jt = maps.find("label");
623 711
	  if (jt == maps.end())
624 712
	    throw DataFormatError("Label map not found in file");
625 713
	  label_index = jt->second;
626 714
	}
627 715
	map_num = maps.size();
628 716
      }
629 717

	
630 718
      char c;
631 719
      while (readLine() && line >> c && c != '@') {
632 720
	line.putback(c);
633 721

	
634 722
	std::vector<std::string> tokens(map_num);
635 723
	for (int i = 0; i < map_num; ++i) {
636 724
	  if (!_reader_bits::readToken(line, tokens[i])) {
637 725
	    std::ostringstream msg;
638 726
	    msg << "Column not found (" << i + 1 << ")";
639 727
	    throw DataFormatError(msg.str().c_str());
640 728
	  }
641 729
	}
642 730
	if (line >> std::ws >> c)
643 731
	  throw DataFormatError("Extra character on the end of line");
644 732
	
645 733
	Node n;
646 734
	if (!_use_nodes) {
647 735
	  n = _digraph.addNode();
648 736
	  _node_index.insert(std::make_pair(tokens[label_index], n));
649 737
	} else {
650 738
	  typename std::map<std::string, Node>::iterator it =
651 739
	    _node_index.find(tokens[label_index]);
652 740
	  if (it == _node_index.end()) {
653 741
	    std::ostringstream msg;
654 742
	    msg << "Node with label not found: " << tokens[label_index];
655 743
	    throw DataFormatError(msg.str().c_str());	    
656 744
	  }
657 745
	  n = it->second;
658 746
	}
659 747

	
660 748
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
661 749
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
662 750
	}
663 751

	
664 752
      }
665 753
      if (readSuccess()) {
666 754
	line.putback(c);
667 755
      }
668 756
    }
669 757

	
670 758
    void readArcs() {
671 759

	
672 760
      std::vector<int> map_index(_arc_maps.size());
673 761
      int map_num, label_index;
674 762

	
675 763
      if (!readLine()) 
676 764
	throw DataFormatError("Cannot find map captions");
677 765
      
678 766
      {
679 767
	std::map<std::string, int> maps;
680 768
	
681 769
	std::string map;
682 770
	int index = 0;
683
	while (_reader_bits::readIdentifier(line, map)) {
771
	while (_reader_bits::readToken(line, map)) {
684 772
	  if (maps.find(map) != maps.end()) {
685 773
	    std::ostringstream msg;
686 774
	    msg << "Multiple occurence of arc map: " << map;
687 775
	    throw DataFormatError(msg.str().c_str());
688 776
	  }
689 777
	  maps.insert(std::make_pair(map, index));
690 778
	  ++index;
691 779
	}
692 780
	
693 781
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
694 782
	  std::map<std::string, int>::iterator jt = 
695 783
	    maps.find(_arc_maps[i].first);
696 784
	  if (jt == maps.end()) {
697 785
	    std::ostringstream msg;
698 786
	    msg << "Map not found in file: " << _arc_maps[i].first;
699 787
	    throw DataFormatError(msg.str().c_str());
700 788
	  }
701 789
	  map_index[i] = jt->second;
702 790
	}
703 791

	
704 792
	{
705 793
	  std::map<std::string, int>::iterator jt = maps.find("label");
706 794
	  if (jt == maps.end())
707 795
	    throw DataFormatError("Label map not found in file");
708 796
	  label_index = jt->second;
709 797
	}
710 798
	map_num = maps.size();
711 799
      }
712 800

	
713 801
      char c;
714 802
      while (readLine() && line >> c && c != '@') {
715 803
	line.putback(c);
716 804

	
717 805
	std::string source_token;
718 806
	std::string target_token;
719 807

	
720 808
	if (!_reader_bits::readToken(line, source_token))
721 809
	  throw DataFormatError("Source not found");
722 810

	
723 811
	if (!_reader_bits::readToken(line, target_token))
724 812
	  throw DataFormatError("Source not found");
725 813
	
726 814
	std::vector<std::string> tokens(map_num);
727 815
	for (int i = 0; i < map_num; ++i) {
728 816
	  if (!_reader_bits::readToken(line, tokens[i])) {
729 817
	    std::ostringstream msg;
730 818
	    msg << "Column not found (" << i + 1 << ")";
731 819
	    throw DataFormatError(msg.str().c_str());
732 820
	  }
733 821
	}
734 822
	if (line >> std::ws >> c)
735 823
	  throw DataFormatError("Extra character on the end of line");
736 824
	
737 825
	Arc a;
738 826
	if (!_use_arcs) {
739 827

	
740 828
          typename NodeIndex::iterator it;
741 829
 
742 830
          it = _node_index.find(source_token);
743 831
          if (it == _node_index.end()) {
744 832
            std::ostringstream msg;
745 833
            msg << "Item not found: " << source_token;
746 834
            throw DataFormatError(msg.str().c_str());
747 835
          }
748 836
          Node source = it->second;
749 837

	
750 838
          it = _node_index.find(target_token);
751 839
          if (it == _node_index.end()) {       
752 840
            std::ostringstream msg;            
753 841
            msg << "Item not found: " << target_token;
754 842
            throw DataFormatError(msg.str().c_str());
755 843
          }                                          
756 844
          Node target = it->second;                            
757 845

	
758 846
	  a = _digraph.addArc(source, target);
759 847
	  _arc_index.insert(std::make_pair(tokens[label_index], a));
760 848
	} else {
761 849
	  typename std::map<std::string, Arc>::iterator it =
762 850
	    _arc_index.find(tokens[label_index]);
763 851
	  if (it == _arc_index.end()) {
764 852
	    std::ostringstream msg;
765 853
	    msg << "Arc with label not found: " << tokens[label_index];
766 854
	    throw DataFormatError(msg.str().c_str());	    
767 855
	  }
768 856
	  a = it->second;
769 857
	}
770 858

	
771 859
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
772 860
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
773 861
	}
774 862

	
775 863
      }
776 864
      if (readSuccess()) {
777 865
	line.putback(c);
778 866
      }
779 867
    }
780 868

	
781 869
    void readAttributes() {
782 870

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

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

	
797 885
	{
798 886
	  std::set<std::string>::iterator it = read_attr.find(attr);
799 887
	  if (it != read_attr.end()) {
800 888
	    std::ostringstream msg;
801 889
	    msg << "Multiple occurence of attribute " << attr;
802 890
	    throw DataFormatError(msg.str().c_str());
803 891
	  }
804 892
	  read_attr.insert(attr);
805 893
	}
806 894
	
807 895
	{
808 896
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
809 897
	  while (it != _attributes.end() && it->first == attr) {
810 898
	    it->second->set(token);
811 899
	    ++it;
812 900
	  }
813 901
	}
814 902

	
815 903
      }
816 904
      if (readSuccess()) {
817 905
	line.putback(c);
818 906
      }
819 907
      for (typename Attributes::iterator it = _attributes.begin();
820 908
	   it != _attributes.end(); ++it) {
821 909
	if (read_attr.find(it->first) == read_attr.end()) {
822 910
	  std::ostringstream msg;
823 911
	  msg << "Attribute not found in file: " << it->first;
824 912
	  throw DataFormatError(msg.str().c_str());
825 913
	}	
826 914
      }
827 915
    }
828 916

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

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

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

	
840 933
      line_num = 0;      
841 934
      readLine();
842 935

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

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

	
855 948
	  if (section == "nodes" && !nodes_done) {
856 949
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
857 950
	      readNodes();
858 951
	      nodes_done = true;
859 952
	    }
860 953
	  } else if ((section == "arcs" || section == "edges") && 
861 954
		     !arcs_done) {
862 955
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
863 956
	      readArcs();
864 957
	      arcs_done = true;
865 958
	    }
866 959
	  } else if (section == "attributes" && !attributes_done) {
867 960
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
868 961
	      readAttributes();
869 962
	      attributes_done = true;
870 963
	    }
871 964
	  } else {
872 965
	    readLine();
873 966
	    skipSection();
874 967
	  }
875 968
	} catch (DataFormatError& error) {
876 969
	  error.line(line_num);
877 970
	  throw;
878 971
	}	
879 972
      }
880 973

	
881 974
      if (!nodes_done) {
882 975
	throw DataFormatError("Section @nodes not found");
883 976
      }
884 977

	
885 978
      if (!arcs_done) {
886 979
	throw DataFormatError("Section @arcs not found");
887 980
      }
888 981

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

	
893 986
    }
987

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

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

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

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

	
914 1012
#endif
Ignore white space 6 line context
... ...
@@ -111,517 +111,628 @@
111 111
    };
112 112

	
113 113
    class ValueStorageBase {
114 114
    public:
115 115
      ValueStorageBase() {}
116 116
      virtual ~ValueStorageBase() {}
117 117

	
118 118
      virtual std::string get() = 0;      
119 119
    };
120 120

	
121 121
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
122 122
    class ValueStorage : public ValueStorageBase {
123 123
    public:
124 124
      typedef _Value Value;
125 125
      typedef _Converter Converter;
126 126

	
127 127
    private:
128 128
      const Value& _value;
129 129
      Converter _converter;
130 130

	
131 131
    public:
132 132
      ValueStorage(const Value& value, const Converter& converter = Converter())
133 133
 	: _value(value), _converter(converter) {}
134 134

	
135 135
      virtual std::string get() {
136 136
	return _converter(_value);
137 137
      }
138 138
    };
139 139

	
140 140
    template <typename Value>
141 141
    struct MapLookUpConverter {
142 142
      const std::map<Value, std::string>& _map;
143 143
      
144 144
      MapLookUpConverter(const std::map<Value, std::string>& map) 
145 145
	: _map(map) {}
146 146
      
147 147
      std::string operator()(const Value& str) {
148 148
	typename std::map<Value, std::string>::const_iterator it = 
149 149
	  _map.find(str);
150 150
	if (it == _map.end()) {
151 151
	  throw DataFormatError("Item not found");
152 152
	}
153 153
	return it->second;
154 154
      }
155 155
    };
156 156

	
157 157
    bool isWhiteSpace(char c) {
158 158
      return c == ' ' || c == '\t' || c == '\v' || 
159 159
        c == '\n' || c == '\r' || c == '\f'; 
160 160
    }
161 161

	
162 162
    bool isEscaped(char c) {
163 163
      return c == '\\' || c == '\"' || c == '\'' || 
164 164
	c == '\a' || c == '\b';
165 165
    }
166 166

	
167 167
    static void writeEscape(std::ostream& os, char c) {
168 168
      switch (c) {
169 169
      case '\\':
170 170
	os << "\\\\";
171 171
	return;
172 172
      case '\"':
173 173
	os << "\\\"";
174 174
	return;
175 175
      case '\a':
176 176
	os << "\\a";
177 177
	return;
178 178
      case '\b':
179 179
	os << "\\b";
180 180
	return;
181 181
      case '\f':
182 182
	os << "\\f";
183 183
	return;
184 184
      case '\r':
185 185
	os << "\\r";
186 186
	return;
187 187
      case '\n':
188 188
	os << "\\n";
189 189
	return;
190 190
      case '\t':
191 191
	os << "\\t";
192 192
	return;
193 193
      case '\v':
194 194
	os << "\\v";
195 195
	return;
196 196
      default:
197 197
	if (c < 0x20) {
198 198
	  os << '\\' << std::oct << static_cast<int>(c);
199 199
	} else {
200 200
	  os << c;
201 201
	}
202 202
	return;
203 203
      }     
204 204
    }
205 205

	
206 206
    bool requireEscape(const std::string& str) {
207
      if (str.empty() || str[0] == '@') return true;
207 208
      std::istringstream is(str);
208 209
      char c;
209 210
      while (is.get(c)) {
210 211
	if (isWhiteSpace(c) || isEscaped(c)) {
211 212
	  return true;
212 213
	}
213 214
      }
214 215
      return false;
215 216
    }
216 217
    
217 218
    std::ostream& writeToken(std::ostream& os, const std::string& str) {
218 219

	
219 220
      if (requireEscape(str)) {
220 221
	os << '\"';
221 222
	for (std::string::const_iterator it = str.begin(); 
222 223
	     it != str.end(); ++it) {
223 224
	  writeEscape(os, *it);
224 225
	}	
225 226
	os << '\"';
226 227
      } else {
227 228
	os << str;
228 229
      }
229 230
      return os;
230 231
    }
231 232

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

	
239 283
    typedef _Digraph Digraph;
240 284
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
241 285
    
242 286
  private:
243 287

	
244 288

	
245 289
    std::ostream* _os;
246 290
    bool local_os;
247 291

	
248 292
    Digraph& _digraph;
249 293

	
250 294
    std::string _nodes_caption;
251 295
    std::string _arcs_caption;
252 296
    std::string _attributes_caption;
253 297
    
254 298
    typedef std::map<Node, std::string> NodeIndex;
255 299
    NodeIndex _node_index;
256 300
    typedef std::map<Arc, std::string> ArcIndex;
257 301
    ArcIndex _arc_index;
258 302

	
259 303
    typedef std::vector<std::pair<std::string, 
260 304
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
261 305
    NodeMaps _node_maps; 
262 306

	
263 307
    typedef std::vector<std::pair<std::string, 
264 308
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
265 309
    ArcMaps _arc_maps;
266 310

	
267 311
    typedef std::vector<std::pair<std::string, 
268 312
      _writer_bits::ValueStorageBase*> > Attributes;
269 313
    Attributes _attributes;
270 314

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

	
274 318
  public:
275 319

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

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

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

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

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

	
298 355
      _node_index.swap(other._node_index);
299 356
      _arc_index.swap(other._arc_index);
300 357

	
301 358
      _node_maps.swap(other._node_maps);
302 359
      _arc_maps.swap(other._arc_maps);
303 360
      _attributes.swap(other._attributes);
304 361

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

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

	
317 374
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
318 375
	   it != _arc_maps.end(); ++it) {
319 376
	delete it->second;
320 377
      }
321 378

	
322 379
      for (typename Attributes::iterator it = _attributes.begin(); 
323 380
	   it != _attributes.end(); ++it) {
324 381
	delete it->second;
325 382
      }
326 383

	
327 384
      if (local_os) {
328 385
	delete _os;
329 386
      }
330 387
    }
331 388

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

	
336 393
  public:
337 394

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
544
    /// @}
545

	
447 546
  private:
448 547

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

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

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

	
474 573
      std::vector<Node> nodes;
475 574
      for (NodeIt n(_digraph); n != INVALID; ++n) {
476 575
	nodes.push_back(n);
477 576
      }
478 577
      
479 578
      if (label == 0) {
480 579
	IdMap<Digraph, Node> id_map(_digraph);
481 580
	_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
482 581
	std::sort(nodes.begin(), nodes.end(), id_less);
483 582
      } else {
484 583
	label->sort(nodes);
485 584
      }
486 585

	
487 586
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
488 587
	Node n = nodes[i];
489 588
	if (label == 0) {
490 589
	  std::ostringstream os;
491 590
	  os << _digraph.id(n);
492 591
	  _writer_bits::writeToken(*_os, os.str());
493 592
	  *_os << '\t';
494 593
	  _node_index.insert(std::make_pair(n, os.str()));
495 594
	}
496 595
	for (typename NodeMaps::iterator it = _node_maps.begin();
497 596
	     it != _node_maps.end(); ++it) {
498 597
	  std::string value = it->second->get(n);
499 598
	  _writer_bits::writeToken(*_os, value);
500 599
	  if (it->first == "label") {
501 600
	    _node_index.insert(std::make_pair(n, value));
502 601
	  }
503 602
	  *_os << '\t';
504 603
	}
505 604
	*_os << std::endl;
506 605
      }
507 606
    }
508 607

	
509 608
    void writeArcs() {
510 609
      _writer_bits::MapStorageBase<Arc>* label = 0;
511 610
      for (typename ArcMaps::iterator it = _arc_maps.begin();
512 611
	   it != _arc_maps.end(); ++it) {
513 612
        if (it->first == "label") {
514 613
	  label = it->second;
515 614
	  break;
516 615
	}
517 616
      }
518 617

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

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

	
535 634
      std::vector<Arc> arcs;
536 635
      for (ArcIt n(_digraph); n != INVALID; ++n) {
537 636
	arcs.push_back(n);
538 637
      }
539 638
      
540 639
      if (label == 0) {
541 640
	IdMap<Digraph, Arc> id_map(_digraph);
542 641
	_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
543 642
	std::sort(arcs.begin(), arcs.end(), id_less);
544 643
      } else {
545 644
	label->sort(arcs);
546 645
      }
547 646

	
548 647
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
549 648
	Arc a = arcs[i];
550 649
	_writer_bits::writeToken(*_os, _node_index.
551 650
				 find(_digraph.source(a))->second);
552 651
	*_os << '\t';
553 652
	_writer_bits::writeToken(*_os, _node_index.
554 653
				 find(_digraph.target(a))->second);
555 654
	*_os << '\t';
556 655
	if (label == 0) {
557 656
	  std::ostringstream os;
558 657
	  os << _digraph.id(a);
559 658
	  _writer_bits::writeToken(*_os, os.str());
560 659
	  *_os << '\t';
561 660
	  _arc_index.insert(std::make_pair(a, os.str()));
562 661
	}
563 662
	for (typename ArcMaps::iterator it = _arc_maps.begin();
564 663
	     it != _arc_maps.end(); ++it) {
565 664
	  std::string value = it->second->get(a);
566 665
	  _writer_bits::writeToken(*_os, value);
567 666
	  if (it->first == "label") {
568 667
	    _arc_index.insert(std::make_pair(a, value));
569 668
	  }
570 669
	  *_os << '\t';
571 670
	}
572 671
	*_os << std::endl;
573 672
      }
574 673
    }
575 674

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

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

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

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

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

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

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

	
627 738
#endif
0 comments (0 inline)