gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Move to private copy constrcutors
0 2 0
default
2 files changed with 201 insertions and 148 deletions:
↑ Collapse diff ↑
Ignore white space 96 line context
... ...
@@ -341,96 +341,108 @@
341 341
	while (is.get(c) && c != '@') {
342 342
	  if (c == '\n') {
343 343
	    ++line_num;
344 344
	  } else if (c == '#') {
345 345
	    getline(is, line);
346 346
	    ++line_num;
347 347
	  } else if (!isWhiteSpace(c)) {
348 348
	    is.putback(c);
349 349
	    getline(is, line);
350 350
	    _functor(line);
351 351
	    ++line_num;
352 352
	  }
353 353
	}
354 354
	if (is) is.putback(c);
355 355
	else if (is.eof()) is.clear();
356 356
      }
357 357
    };
358 358

	
359 359
    template <typename Functor>
360 360
    class StreamSection : public Section {
361 361
    private:
362 362

	
363 363
      Functor _functor;
364 364

	
365 365
    public:
366 366
      
367 367
      StreamSection(const Functor& functor) : _functor(functor) {}
368 368
      virtual ~StreamSection() {} 
369 369

	
370 370
      virtual void process(std::istream& is, int& line_num) {
371 371
	_functor(is, line_num);
372 372
	char c;
373 373
	std::string line;
374 374
	while (is.get(c) && c != '@') {
375 375
	  if (c == '\n') {
376 376
	    ++line_num;
377 377
	  } else if (!isWhiteSpace(c)) {
378 378
	    getline(is, line);
379 379
	    ++line_num;
380 380
	  }
381 381
	}
382 382
	if (is) is.putback(c);
383 383
	else if (is.eof()) is.clear();	
384 384
      }
385 385
    };
386 386
    
387 387
  }
388 388

	
389
  template <typename Digraph>
390
  class DigraphReader;
391

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

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

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

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

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

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

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

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

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

	
483 495
  public:
484 496

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

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

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

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

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

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

	
535
    }
536

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

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

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

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

	
558 545
    }
559 546

	
560 547
  private:
561
    
548

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

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

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

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

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

	
575
    }
576

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

	
564 579
  public:
565 580

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

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

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

	
607 622
    /// \brief Arc map reading rule
608 623
    ///
609 624
    /// Add an arc map reading rule with specialized converter to the
... ...
@@ -1137,224 +1152,236 @@
1137 1152
	    skipSection();
1138 1153
	  }
1139 1154
	} catch (DataFormatError& error) {
1140 1155
	  error.line(line_num);
1141 1156
	  throw;
1142 1157
	}	
1143 1158
      }
1144 1159

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

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

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

	
1157 1172
    }
1158 1173

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

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

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

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

	
1200
  template <typename Graph>
1201
  class GraphReader;
1202

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

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

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

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

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

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

	
1202 1229
    Graph& _graph;
1203 1230

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

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

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

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

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

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

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

	
1234 1261
  public:
1235 1262

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

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

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

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

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

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

	
1286
    }
1287

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

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

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

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

	
1309 1311
    }
1310 1312

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

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

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

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

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

	
1338
    }
1339

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

	
1315 1342
  public:
1316 1343

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

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

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

	
1358 1385
    /// \brief Edge map reading rule
1359 1386
    ///
1360 1387
    /// Add an edge map reading rule with specialized converter to the
... ...
@@ -1932,165 +1959,171 @@
1932 1959
	    skipSection();
1933 1960
	  }
1934 1961
	} catch (DataFormatError& error) {
1935 1962
	  error.line(line_num);
1936 1963
	  throw;
1937 1964
	}	
1938 1965
      }
1939 1966

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

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

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

	
1952 1979
    }
1953 1980

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

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

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

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

	
2007
  class SectionReader;
2008

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

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

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

	
2001 2034
  public:
2002 2035

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

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

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

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

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

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

	
2046 2066
    }
2047 2067

	
2048 2068
  private:
2069

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

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

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

	
2052 2085
  public:
2053 2086

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

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

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

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

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

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

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

	
2272 2305

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

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

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

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

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

	
2314
      _arc_sections.swap(other._arc_sections);
2315

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

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

	
2342
  public:
2343

	
2326 2344

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

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

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

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

	
2351 2369
    /// @}
2352 2370

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

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

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

	
2372 2390
    /// \brief Gives back the arc/edge maps for the given section.
2373 2391
    ///
Ignore white space 6 line context
... ...
@@ -259,252 +259,270 @@
259 259
	os << "\\n";
260 260
	return;
261 261
      case '\t':
262 262
	os << "\\t";
263 263
	return;
264 264
      case '\v':
265 265
	os << "\\v";
266 266
	return;
267 267
      default:
268 268
	if (c < 0x20) {
269 269
	  std::ios::fmtflags flags = os.flags();
270 270
	  os << '\\' << std::oct << static_cast<int>(c);
271 271
	  os.flags(flags);
272 272
	} else {
273 273
	  os << c;
274 274
	}
275 275
	return;
276 276
      }     
277 277
    }
278 278

	
279 279
    bool requireEscape(const std::string& str) {
280 280
      if (str.empty() || str[0] == '@') return true;
281 281
      std::istringstream is(str);
282 282
      char c;
283 283
      while (is.get(c)) {
284 284
	if (isWhiteSpace(c) || isEscaped(c)) {
285 285
	  return true;
286 286
	}
287 287
      }
288 288
      return false;
289 289
    }
290 290
    
291 291
    std::ostream& writeToken(std::ostream& os, const std::string& str) {
292 292

	
293 293
      if (requireEscape(str)) {
294 294
	os << '\"';
295 295
	for (std::string::const_iterator it = str.begin(); 
296 296
	     it != str.end(); ++it) {
297 297
	  writeEscape(os, *it);
298 298
	}	
299 299
	os << '\"';
300 300
      } else {
301 301
	os << str;
302 302
      }
303 303
      return os;
304 304
    }
305 305

	
306 306
  }
307

	
308
  template <typename Digraph>
309
  class DigraphWriter;
310

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

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

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

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

	
361 376

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

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

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

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

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

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

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

	
391 406
  public:
392 407

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

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

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

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

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

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

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

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

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

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

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

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

	
462 454
  private:
455

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

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

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

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

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

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

	
466 484
  public:
467 485

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

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

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

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

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

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

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

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

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

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

	
887
  template <typename Graph>
888
  class GraphWriter;
889

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

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

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

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

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

	
881 913

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

	
885 917
    Graph& _graph;
886 918

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

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

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

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

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

	
911 943
  public:
912 944

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
986 1021
  public:
987 1022

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

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

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

	
1029 1064
    /// \brief Edge map writing rule
1030 1065
    ///
1031 1066
    /// Add an edge map writing rule with specialized converter to the
... ...
@@ -1365,69 +1400,69 @@
1365 1400
      if (_attributes.empty()) return;
1366 1401
      *_os << "@attributes";
1367 1402
      if (!_attributes_caption.empty()) {
1368 1403
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
1369 1404
      }
1370 1405
      *_os << std::endl;
1371 1406
      for (typename Attributes::iterator it = _attributes.begin();
1372 1407
	   it != _attributes.end(); ++it) {
1373 1408
	_writer_bits::writeToken(*_os, it->first) << ' ';
1374 1409
	_writer_bits::writeToken(*_os, it->second->get());
1375 1410
	*_os << std::endl;
1376 1411
      }
1377 1412
    }
1378 1413
    
1379 1414
  public:
1380 1415
    
1381 1416
    /// \name Execution of the writer    
1382 1417
    /// @{
1383 1418

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

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

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

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

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

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

	
1433 1468
#endif
0 comments (0 inline)