gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Fix memory leak hazard If the constructor throws an exception, it should deallocate each dynamically allocated memory.
0 2 0
default
2 files changed with 56 insertions and 14 deletions:
↑ Collapse diff ↑
Ignore white space 192 line context
... ...
@@ -424,205 +424,211 @@
424 424
  ///\code
425 425
  /// DigraphReader<Digraph>(digraph, std::cin).
426 426
  ///   nodeMap("coordinates", coord_map).
427 427
  ///   arcMap("capacity", cap_map).
428 428
  ///   node("source", src).
429 429
  ///   node("target", trg).
430 430
  ///   attribute("caption", caption).
431 431
  ///   run();
432 432
  ///\endcode
433 433
  ///
434 434
  /// By default the reader uses the first section in the file of the
435 435
  /// proper type. If a section has an optional name, then it can be
436 436
  /// selected for reading by giving an optional name parameter to the
437 437
  /// \c nodes(), \c arcs() or \c attributes() functions.
438 438
  ///
439 439
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
440 440
  /// that the nodes or arcs should not be constructed (added to the
441 441
  /// graph) during the reading, but instead the label map of the items
442 442
  /// are given as a parameter of these functions. An
443 443
  /// application of these functions is multipass reading, which is
444 444
  /// important if two \c \@arcs sections must be read from the
445 445
  /// file. In this case the first phase would read the node set and one
446 446
  /// of the arc sets, while the second phase would read the second arc
447 447
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
448 448
  /// The previously read label node map should be passed to the \c
449 449
  /// useNodes() functions. Another application of multipass reading when
450 450
  /// paths are given as a node map or an arc map.
451 451
  /// It is impossible to read this in
452 452
  /// a single pass, because the arcs are not constructed when the node
453 453
  /// maps are read.
454 454
  template <typename _Digraph>
455 455
  class DigraphReader {
456 456
  public:
457 457

	
458 458
    typedef _Digraph Digraph;
459 459
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
460 460

	
461 461
  private:
462 462

	
463 463

	
464 464
    std::istream* _is;
465 465
    bool local_is;
466 466
    std::string _filename;
467 467

	
468 468
    Digraph& _digraph;
469 469

	
470 470
    std::string _nodes_caption;
471 471
    std::string _arcs_caption;
472 472
    std::string _attributes_caption;
473 473

	
474 474
    typedef std::map<std::string, Node> NodeIndex;
475 475
    NodeIndex _node_index;
476 476
    typedef std::map<std::string, Arc> ArcIndex;
477 477
    ArcIndex _arc_index;
478 478

	
479 479
    typedef std::vector<std::pair<std::string,
480 480
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
481 481
    NodeMaps _node_maps;
482 482

	
483 483
    typedef std::vector<std::pair<std::string,
484 484
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
485 485
    ArcMaps _arc_maps;
486 486

	
487 487
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
488 488
      Attributes;
489 489
    Attributes _attributes;
490 490

	
491 491
    bool _use_nodes;
492 492
    bool _use_arcs;
493 493

	
494 494
    bool _skip_nodes;
495 495
    bool _skip_arcs;
496 496

	
497 497
    int line_num;
498 498
    std::istringstream line;
499 499

	
500 500
  public:
501 501

	
502 502
    /// \brief Constructor
503 503
    ///
504 504
    /// Construct a directed graph reader, which reads from the given
505 505
    /// input stream.
506 506
    DigraphReader(Digraph& digraph, std::istream& is = std::cin)
507 507
      : _is(&is), local_is(false), _digraph(digraph),
508 508
        _use_nodes(false), _use_arcs(false),
509 509
        _skip_nodes(false), _skip_arcs(false) {}
510 510

	
511 511
    /// \brief Constructor
512 512
    ///
513 513
    /// Construct a directed graph reader, which reads from the given
514 514
    /// file.
515 515
    DigraphReader(Digraph& digraph, const std::string& fn)
516 516
      : _is(new std::ifstream(fn.c_str())), local_is(true),
517 517
        _filename(fn), _digraph(digraph),
518 518
        _use_nodes(false), _use_arcs(false),
519 519
        _skip_nodes(false), _skip_arcs(false) {
520
      if (!(*_is)) throw IoError("Cannot open file", fn);
520
      if (!(*_is)) {
521
        delete _is;
522
        throw IoError("Cannot open file", fn);
523
      }
521 524
    }
522 525

	
523 526
    /// \brief Constructor
524 527
    ///
525 528
    /// Construct a directed graph reader, which reads from the given
526 529
    /// file.
527 530
    DigraphReader(Digraph& digraph, const char* fn)
528 531
      : _is(new std::ifstream(fn)), local_is(true),
529 532
        _filename(fn), _digraph(digraph),
530 533
        _use_nodes(false), _use_arcs(false),
531 534
        _skip_nodes(false), _skip_arcs(false) {
532
      if (!(*_is)) throw IoError("Cannot open file", fn);
535
      if (!(*_is)) {
536
        delete _is;
537
        throw IoError("Cannot open file", fn);
538
      }
533 539
    }
534 540

	
535 541
    /// \brief Destructor
536 542
    ~DigraphReader() {
537 543
      for (typename NodeMaps::iterator it = _node_maps.begin();
538 544
           it != _node_maps.end(); ++it) {
539 545
        delete it->second;
540 546
      }
541 547

	
542 548
      for (typename ArcMaps::iterator it = _arc_maps.begin();
543 549
           it != _arc_maps.end(); ++it) {
544 550
        delete it->second;
545 551
      }
546 552

	
547 553
      for (typename Attributes::iterator it = _attributes.begin();
548 554
           it != _attributes.end(); ++it) {
549 555
        delete it->second;
550 556
      }
551 557

	
552 558
      if (local_is) {
553 559
        delete _is;
554 560
      }
555 561

	
556 562
    }
557 563

	
558 564
  private:
559 565

	
560 566
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
561 567
                                                  std::istream& is);
562 568
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
563 569
                                                  const std::string& fn);
564 570
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
565 571
                                                  const char *fn);
566 572

	
567 573
    DigraphReader(DigraphReader& other)
568 574
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
569 575
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
570 576
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
571 577

	
572 578
      other._is = 0;
573 579
      other.local_is = false;
574 580

	
575 581
      _node_index.swap(other._node_index);
576 582
      _arc_index.swap(other._arc_index);
577 583

	
578 584
      _node_maps.swap(other._node_maps);
579 585
      _arc_maps.swap(other._arc_maps);
580 586
      _attributes.swap(other._attributes);
581 587

	
582 588
      _nodes_caption = other._nodes_caption;
583 589
      _arcs_caption = other._arcs_caption;
584 590
      _attributes_caption = other._attributes_caption;
585 591

	
586 592
    }
587 593

	
588 594
    DigraphReader& operator=(const DigraphReader&);
589 595

	
590 596
  public:
591 597

	
592 598
    /// \name Reading rules
593 599
    /// @{
594 600

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

	
607 613
    /// \brief Node map reading rule
608 614
    ///
609 615
    /// Add a node map reading rule with specialized converter to the
610 616
    /// reader.
611 617
    template <typename Map, typename Converter>
612 618
    DigraphReader& nodeMap(const std::string& caption, Map& map,
613 619
                           const Converter& converter = Converter()) {
614 620
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
615 621
      _reader_bits::MapStorageBase<Node>* storage =
616 622
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
617 623
      _node_maps.push_back(std::make_pair(caption, storage));
618 624
      return *this;
619 625
    }
620 626

	
621 627
    /// \brief Arc map reading rule
622 628
    ///
623 629
    /// Add an arc map reading rule to the reader.
624 630
    template <typename Map>
625 631
    DigraphReader& arcMap(const std::string& caption, Map& map) {
626 632
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
627 633
      _reader_bits::MapStorageBase<Arc>* storage =
628 634
        new _reader_bits::MapStorage<Arc, Map>(map);
... ...
@@ -1215,205 +1221,211 @@
1215 1221
    return tmp;
1216 1222
  }
1217 1223

	
1218 1224
  template <typename Graph>
1219 1225
  class GraphReader;
1220 1226

	
1221 1227
  template <typename Graph>
1222 1228
  GraphReader<Graph> graphReader(Graph& graph,
1223 1229
                                 std::istream& is = std::cin);
1224 1230

	
1225 1231
  template <typename Graph>
1226 1232
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn);
1227 1233

	
1228 1234
  template <typename Graph>
1229 1235
  GraphReader<Graph> graphReader(Graph& graph, const char *fn);
1230 1236

	
1231 1237
  /// \ingroup lemon_io
1232 1238
  ///
1233 1239
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
1234 1240
  ///
1235 1241
  /// This utility reads an \ref lgf-format "LGF" file.
1236 1242
  ///
1237 1243
  /// It can be used almost the same way as \c DigraphReader.
1238 1244
  /// The only difference is that this class can handle edges and
1239 1245
  /// edge maps as well as arcs and arc maps.
1240 1246
  ///
1241 1247
  /// The columns in the \c \@edges (or \c \@arcs) section are the
1242 1248
  /// edge maps. However, if there are two maps with the same name
1243 1249
  /// prefixed with \c '+' and \c '-', then these can be read into an
1244 1250
  /// arc map.  Similarly, an attribute can be read into an arc, if
1245 1251
  /// it's value is an edge label prefixed with \c '+' or \c '-'.
1246 1252
  template <typename _Graph>
1247 1253
  class GraphReader {
1248 1254
  public:
1249 1255

	
1250 1256
    typedef _Graph Graph;
1251 1257
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1252 1258

	
1253 1259
  private:
1254 1260

	
1255 1261
    std::istream* _is;
1256 1262
    bool local_is;
1257 1263
    std::string _filename;
1258 1264

	
1259 1265
    Graph& _graph;
1260 1266

	
1261 1267
    std::string _nodes_caption;
1262 1268
    std::string _edges_caption;
1263 1269
    std::string _attributes_caption;
1264 1270

	
1265 1271
    typedef std::map<std::string, Node> NodeIndex;
1266 1272
    NodeIndex _node_index;
1267 1273
    typedef std::map<std::string, Edge> EdgeIndex;
1268 1274
    EdgeIndex _edge_index;
1269 1275

	
1270 1276
    typedef std::vector<std::pair<std::string,
1271 1277
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1272 1278
    NodeMaps _node_maps;
1273 1279

	
1274 1280
    typedef std::vector<std::pair<std::string,
1275 1281
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1276 1282
    EdgeMaps _edge_maps;
1277 1283

	
1278 1284
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1279 1285
      Attributes;
1280 1286
    Attributes _attributes;
1281 1287

	
1282 1288
    bool _use_nodes;
1283 1289
    bool _use_edges;
1284 1290

	
1285 1291
    bool _skip_nodes;
1286 1292
    bool _skip_edges;
1287 1293

	
1288 1294
    int line_num;
1289 1295
    std::istringstream line;
1290 1296

	
1291 1297
  public:
1292 1298

	
1293 1299
    /// \brief Constructor
1294 1300
    ///
1295 1301
    /// Construct an undirected graph reader, which reads from the given
1296 1302
    /// input stream.
1297 1303
    GraphReader(Graph& graph, std::istream& is = std::cin)
1298 1304
      : _is(&is), local_is(false), _graph(graph),
1299 1305
        _use_nodes(false), _use_edges(false),
1300 1306
        _skip_nodes(false), _skip_edges(false) {}
1301 1307

	
1302 1308
    /// \brief Constructor
1303 1309
    ///
1304 1310
    /// Construct an undirected graph reader, which reads from the given
1305 1311
    /// file.
1306 1312
    GraphReader(Graph& graph, const std::string& fn)
1307 1313
      : _is(new std::ifstream(fn.c_str())), local_is(true),
1308 1314
        _filename(fn), _graph(graph),
1309 1315
        _use_nodes(false), _use_edges(false),
1310 1316
        _skip_nodes(false), _skip_edges(false) {
1311
      if (!(*_is)) throw IoError("Cannot open file", fn);
1317
      if (!(*_is)) {
1318
        delete _is;
1319
        throw IoError("Cannot open file", fn);
1320
      }
1312 1321
    }
1313 1322

	
1314 1323
    /// \brief Constructor
1315 1324
    ///
1316 1325
    /// Construct an undirected graph reader, which reads from the given
1317 1326
    /// file.
1318 1327
    GraphReader(Graph& graph, const char* fn)
1319 1328
      : _is(new std::ifstream(fn)), local_is(true),
1320 1329
        _filename(fn), _graph(graph),
1321 1330
        _use_nodes(false), _use_edges(false),
1322 1331
        _skip_nodes(false), _skip_edges(false) {
1323
      if (!(*_is)) throw IoError("Cannot open file", fn);
1332
      if (!(*_is)) {
1333
        delete _is;
1334
        throw IoError("Cannot open file", fn);
1335
      }
1324 1336
    }
1325 1337

	
1326 1338
    /// \brief Destructor
1327 1339
    ~GraphReader() {
1328 1340
      for (typename NodeMaps::iterator it = _node_maps.begin();
1329 1341
           it != _node_maps.end(); ++it) {
1330 1342
        delete it->second;
1331 1343
      }
1332 1344

	
1333 1345
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1334 1346
           it != _edge_maps.end(); ++it) {
1335 1347
        delete it->second;
1336 1348
      }
1337 1349

	
1338 1350
      for (typename Attributes::iterator it = _attributes.begin();
1339 1351
           it != _attributes.end(); ++it) {
1340 1352
        delete it->second;
1341 1353
      }
1342 1354

	
1343 1355
      if (local_is) {
1344 1356
        delete _is;
1345 1357
      }
1346 1358

	
1347 1359
    }
1348 1360

	
1349 1361
  private:
1350 1362
    friend GraphReader<Graph> graphReader<>(Graph& graph, std::istream& is);
1351 1363
    friend GraphReader<Graph> graphReader<>(Graph& graph,
1352 1364
                                            const std::string& fn);
1353 1365
    friend GraphReader<Graph> graphReader<>(Graph& graph, const char *fn);
1354 1366

	
1355 1367
    GraphReader(GraphReader& other)
1356 1368
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1357 1369
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1358 1370
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1359 1371

	
1360 1372
      other._is = 0;
1361 1373
      other.local_is = false;
1362 1374

	
1363 1375
      _node_index.swap(other._node_index);
1364 1376
      _edge_index.swap(other._edge_index);
1365 1377

	
1366 1378
      _node_maps.swap(other._node_maps);
1367 1379
      _edge_maps.swap(other._edge_maps);
1368 1380
      _attributes.swap(other._attributes);
1369 1381

	
1370 1382
      _nodes_caption = other._nodes_caption;
1371 1383
      _edges_caption = other._edges_caption;
1372 1384
      _attributes_caption = other._attributes_caption;
1373 1385

	
1374 1386
    }
1375 1387

	
1376 1388
    GraphReader& operator=(const GraphReader&);
1377 1389

	
1378 1390
  public:
1379 1391

	
1380 1392
    /// \name Reading rules
1381 1393
    /// @{
1382 1394

	
1383 1395
    /// \brief Node map reading rule
1384 1396
    ///
1385 1397
    /// Add a node map reading rule to the reader.
1386 1398
    template <typename Map>
1387 1399
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1388 1400
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1389 1401
      _reader_bits::MapStorageBase<Node>* storage =
1390 1402
        new _reader_bits::MapStorage<Node, Map>(map);
1391 1403
      _node_maps.push_back(std::make_pair(caption, storage));
1392 1404
      return *this;
1393 1405
    }
1394 1406

	
1395 1407
    /// \brief Node map reading rule
1396 1408
    ///
1397 1409
    /// Add a node map reading rule with specialized converter to the
1398 1410
    /// reader.
1399 1411
    template <typename Map, typename Converter>
1400 1412
    GraphReader& nodeMap(const std::string& caption, Map& map,
1401 1413
                           const Converter& converter = Converter()) {
1402 1414
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1403 1415
      _reader_bits::MapStorageBase<Node>* storage =
1404 1416
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1405 1417
      _node_maps.push_back(std::make_pair(caption, storage));
1406 1418
      return *this;
1407 1419
    }
1408 1420

	
1409 1421
    /// \brief Edge map reading rule
1410 1422
    ///
1411 1423
    /// Add an edge map reading rule to the reader.
1412 1424
    template <typename Map>
1413 1425
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1414 1426
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1415 1427
      _reader_bits::MapStorageBase<Edge>* storage =
1416 1428
        new _reader_bits::MapStorage<Edge, Map>(map);
1417 1429
      _edge_maps.push_back(std::make_pair(caption, storage));
1418 1430
      return *this;
1419 1431
    }
... ...
@@ -2001,202 +2013,208 @@
2001 2013
        }
2002 2014
      }
2003 2015

	
2004 2016
      if (!nodes_done) {
2005 2017
        throw FormatError("Section @nodes not found");
2006 2018
      }
2007 2019

	
2008 2020
      if (!edges_done) {
2009 2021
        throw FormatError("Section @edges not found");
2010 2022
      }
2011 2023

	
2012 2024
      if (!attributes_done && !_attributes.empty()) {
2013 2025
        throw FormatError("Section @attributes not found");
2014 2026
      }
2015 2027

	
2016 2028
    }
2017 2029

	
2018 2030
    /// @}
2019 2031

	
2020 2032
  };
2021 2033

	
2022 2034
  /// \brief Return a \ref GraphReader class
2023 2035
  ///
2024 2036
  /// This function just returns a \ref GraphReader class.
2025 2037
  /// \relates GraphReader
2026 2038
  template <typename Graph>
2027 2039
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is = std::cin) {
2028 2040
    GraphReader<Graph> tmp(graph, is);
2029 2041
    return tmp;
2030 2042
  }
2031 2043

	
2032 2044
  /// \brief Return a \ref GraphReader class
2033 2045
  ///
2034 2046
  /// This function just returns a \ref GraphReader class.
2035 2047
  /// \relates GraphReader
2036 2048
  template <typename Graph>
2037 2049
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn) {
2038 2050
    GraphReader<Graph> tmp(graph, fn);
2039 2051
    return tmp;
2040 2052
  }
2041 2053

	
2042 2054
  /// \brief Return a \ref GraphReader class
2043 2055
  ///
2044 2056
  /// This function just returns a \ref GraphReader class.
2045 2057
  /// \relates GraphReader
2046 2058
  template <typename Graph>
2047 2059
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
2048 2060
    GraphReader<Graph> tmp(graph, fn);
2049 2061
    return tmp;
2050 2062
  }
2051 2063

	
2052 2064
  class SectionReader;
2053 2065

	
2054 2066
  SectionReader sectionReader(std::istream& is);
2055 2067
  SectionReader sectionReader(const std::string& fn);
2056 2068
  SectionReader sectionReader(const char* fn);
2057 2069

	
2058 2070
  /// \ingroup lemon_io
2059 2071
  ///
2060 2072
  /// \brief Section reader class
2061 2073
  ///
2062 2074
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
2063 2075
  /// which contain any data in arbitrary format. Such sections can be
2064 2076
  /// read with this class. A reading rule can be added to the class
2065 2077
  /// with two different functions. With the \c sectionLines() function a
2066 2078
  /// functor can process the section line-by-line, while with the \c
2067 2079
  /// sectionStream() member the section can be read from an input
2068 2080
  /// stream.
2069 2081
  class SectionReader {
2070 2082
  private:
2071 2083

	
2072 2084
    std::istream* _is;
2073 2085
    bool local_is;
2074 2086
    std::string _filename;
2075 2087

	
2076 2088
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2077 2089
    Sections _sections;
2078 2090

	
2079 2091
    int line_num;
2080 2092
    std::istringstream line;
2081 2093

	
2082 2094
  public:
2083 2095

	
2084 2096
    /// \brief Constructor
2085 2097
    ///
2086 2098
    /// Construct a section reader, which reads from the given input
2087 2099
    /// stream.
2088 2100
    SectionReader(std::istream& is)
2089 2101
      : _is(&is), local_is(false) {}
2090 2102

	
2091 2103
    /// \brief Constructor
2092 2104
    ///
2093 2105
    /// Construct a section reader, which reads from the given file.
2094 2106
    SectionReader(const std::string& fn)
2095 2107
      : _is(new std::ifstream(fn.c_str())), local_is(true),
2096 2108
        _filename(fn) {
2097
      if (!(*_is)) throw IoError("Cannot open file", fn);
2109
      if (!(*_is)) {
2110
        delete _is;
2111
        throw IoError("Cannot open file", fn);
2112
      }
2098 2113
    }
2099 2114

	
2100 2115
    /// \brief Constructor
2101 2116
    ///
2102 2117
    /// Construct a section reader, which reads from the given file.
2103 2118
    SectionReader(const char* fn)
2104 2119
      : _is(new std::ifstream(fn)), local_is(true),
2105 2120
        _filename(fn) {
2106
      if (!(*_is)) throw IoError("Cannot open file", fn);
2121
      if (!(*_is)) {
2122
        delete _is;
2123
        throw IoError("Cannot open file", fn);
2124
      }
2107 2125
    }
2108 2126

	
2109 2127
    /// \brief Destructor
2110 2128
    ~SectionReader() {
2111 2129
      for (Sections::iterator it = _sections.begin();
2112 2130
           it != _sections.end(); ++it) {
2113 2131
        delete it->second;
2114 2132
      }
2115 2133

	
2116 2134
      if (local_is) {
2117 2135
        delete _is;
2118 2136
      }
2119 2137

	
2120 2138
    }
2121 2139

	
2122 2140
  private:
2123 2141

	
2124 2142
    friend SectionReader sectionReader(std::istream& is);
2125 2143
    friend SectionReader sectionReader(const std::string& fn);
2126 2144
    friend SectionReader sectionReader(const char* fn);
2127 2145

	
2128 2146
    SectionReader(SectionReader& other)
2129 2147
      : _is(other._is), local_is(other.local_is) {
2130 2148

	
2131 2149
      other._is = 0;
2132 2150
      other.local_is = false;
2133 2151

	
2134 2152
      _sections.swap(other._sections);
2135 2153
    }
2136 2154

	
2137 2155
    SectionReader& operator=(const SectionReader&);
2138 2156

	
2139 2157
  public:
2140 2158

	
2141 2159
    /// \name Section readers
2142 2160
    /// @{
2143 2161

	
2144 2162
    /// \brief Add a section processor with line oriented reading
2145 2163
    ///
2146 2164
    /// The first parameter is the type descriptor of the section, the
2147 2165
    /// second is a functor, which takes just one \c std::string
2148 2166
    /// parameter. At the reading process, each line of the section
2149 2167
    /// will be given to the functor object. However, the empty lines
2150 2168
    /// and the comment lines are filtered out, and the leading
2151 2169
    /// whitespaces are trimmed from each processed string.
2152 2170
    ///
2153 2171
    /// For example let's see a section, which contain several
2154 2172
    /// integers, which should be inserted into a vector.
2155 2173
    ///\code
2156 2174
    ///  @numbers
2157 2175
    ///  12 45 23
2158 2176
    ///  4
2159 2177
    ///  23 6
2160 2178
    ///\endcode
2161 2179
    ///
2162 2180
    /// The functor is implemented as a struct:
2163 2181
    ///\code
2164 2182
    ///  struct NumberSection {
2165 2183
    ///    std::vector<int>& _data;
2166 2184
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2167 2185
    ///    void operator()(const std::string& line) {
2168 2186
    ///      std::istringstream ls(line);
2169 2187
    ///      int value;
2170 2188
    ///      while (ls >> value) _data.push_back(value);
2171 2189
    ///    }
2172 2190
    ///  };
2173 2191
    ///
2174 2192
    ///  // ...
2175 2193
    ///
2176 2194
    ///  reader.sectionLines("numbers", NumberSection(vec));
2177 2195
    ///\endcode
2178 2196
    template <typename Functor>
2179 2197
    SectionReader& sectionLines(const std::string& type, Functor functor) {
2180 2198
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2181 2199
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
2182 2200
                   "Multiple reading of section.");
2183 2201
      _sections.insert(std::make_pair(type,
2184 2202
        new _reader_bits::LineSection<Functor>(functor)));
2185 2203
      return *this;
2186 2204
    }
2187 2205

	
2188 2206

	
2189 2207
    /// \brief Add a section processor with stream oriented reading
2190 2208
    ///
2191 2209
    /// The first parameter is the type of the section, the second is
2192 2210
    /// a functor, which takes an \c std::istream& and an \c int&
2193 2211
    /// parameter, the latter regard to the line number of stream. The
2194 2212
    /// functor can read the input while the section go on, and the
2195 2213
    /// line number should be modified accordingly.
2196 2214
    template <typename Functor>
2197 2215
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2198 2216
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2199 2217
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
2200 2218
                   "Multiple reading of section.");
2201 2219
      _sections.insert(std::make_pair(type,
2202 2220
         new _reader_bits::StreamSection<Functor>(functor)));
... ...
@@ -2293,202 +2311,208 @@
2293 2311
    /// @}
2294 2312

	
2295 2313
  };
2296 2314

	
2297 2315
  /// \brief Return a \ref SectionReader class
2298 2316
  ///
2299 2317
  /// This function just returns a \ref SectionReader class.
2300 2318
  /// \relates SectionReader
2301 2319
  inline SectionReader sectionReader(std::istream& is) {
2302 2320
    SectionReader tmp(is);
2303 2321
    return tmp;
2304 2322
  }
2305 2323

	
2306 2324
  /// \brief Return a \ref SectionReader class
2307 2325
  ///
2308 2326
  /// This function just returns a \ref SectionReader class.
2309 2327
  /// \relates SectionReader
2310 2328
  inline SectionReader sectionReader(const std::string& fn) {
2311 2329
    SectionReader tmp(fn);
2312 2330
    return tmp;
2313 2331
  }
2314 2332

	
2315 2333
  /// \brief Return a \ref SectionReader class
2316 2334
  ///
2317 2335
  /// This function just returns a \ref SectionReader class.
2318 2336
  /// \relates SectionReader
2319 2337
  inline SectionReader sectionReader(const char* fn) {
2320 2338
    SectionReader tmp(fn);
2321 2339
    return tmp;
2322 2340
  }
2323 2341

	
2324 2342
  /// \ingroup lemon_io
2325 2343
  ///
2326 2344
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file
2327 2345
  ///
2328 2346
  /// This class can be used to read the sections, the map names and
2329 2347
  /// the attributes from a file. Usually, the LEMON programs know
2330 2348
  /// that, which type of graph, which maps and which attributes
2331 2349
  /// should be read from a file, but in general tools (like glemon)
2332 2350
  /// the contents of an LGF file should be guessed somehow. This class
2333 2351
  /// reads the graph and stores the appropriate information for
2334 2352
  /// reading the graph.
2335 2353
  ///
2336 2354
  ///\code
2337 2355
  /// LgfContents contents("graph.lgf");
2338 2356
  /// contents.run();
2339 2357
  ///
2340 2358
  /// // Does it contain any node section and arc section?
2341 2359
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2342 2360
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
2343 2361
  ///   return -1;
2344 2362
  /// }
2345 2363
  /// std::cout << "The name of the default node section: "
2346 2364
  ///           << contents.nodeSection(0) << std::endl;
2347 2365
  /// std::cout << "The number of the arc maps: "
2348 2366
  ///           << contents.arcMaps(0).size() << std::endl;
2349 2367
  /// std::cout << "The name of second arc map: "
2350 2368
  ///           << contents.arcMaps(0)[1] << std::endl;
2351 2369
  ///\endcode
2352 2370
  class LgfContents {
2353 2371
  private:
2354 2372

	
2355 2373
    std::istream* _is;
2356 2374
    bool local_is;
2357 2375

	
2358 2376
    std::vector<std::string> _node_sections;
2359 2377
    std::vector<std::string> _edge_sections;
2360 2378
    std::vector<std::string> _attribute_sections;
2361 2379
    std::vector<std::string> _extra_sections;
2362 2380

	
2363 2381
    std::vector<bool> _arc_sections;
2364 2382

	
2365 2383
    std::vector<std::vector<std::string> > _node_maps;
2366 2384
    std::vector<std::vector<std::string> > _edge_maps;
2367 2385

	
2368 2386
    std::vector<std::vector<std::string> > _attributes;
2369 2387

	
2370 2388

	
2371 2389
    int line_num;
2372 2390
    std::istringstream line;
2373 2391

	
2374 2392
  public:
2375 2393

	
2376 2394
    /// \brief Constructor
2377 2395
    ///
2378 2396
    /// Construct an \e LGF contents reader, which reads from the given
2379 2397
    /// input stream.
2380 2398
    LgfContents(std::istream& is)
2381 2399
      : _is(&is), local_is(false) {}
2382 2400

	
2383 2401
    /// \brief Constructor
2384 2402
    ///
2385 2403
    /// Construct an \e LGF contents reader, which reads from the given
2386 2404
    /// file.
2387 2405
    LgfContents(const std::string& fn)
2388 2406
      : _is(new std::ifstream(fn.c_str())), local_is(true) {
2389
      if (!(*_is)) throw IoError("Cannot open file", fn);
2407
      if (!(*_is)) {
2408
        delete _is;
2409
        throw IoError("Cannot open file", fn);
2410
      }
2390 2411
    }
2391 2412

	
2392 2413
    /// \brief Constructor
2393 2414
    ///
2394 2415
    /// Construct an \e LGF contents reader, which reads from the given
2395 2416
    /// file.
2396 2417
    LgfContents(const char* fn)
2397 2418
      : _is(new std::ifstream(fn)), local_is(true) {
2398
      if (!(*_is)) throw IoError("Cannot open file", fn);
2419
      if (!(*_is)) {
2420
        delete _is;
2421
        throw IoError("Cannot open file", fn);
2422
      }
2399 2423
    }
2400 2424

	
2401 2425
    /// \brief Destructor
2402 2426
    ~LgfContents() {
2403 2427
      if (local_is) delete _is;
2404 2428
    }
2405 2429

	
2406 2430
  private:
2407 2431

	
2408 2432
    LgfContents(const LgfContents&);
2409 2433
    LgfContents& operator=(const LgfContents&);
2410 2434

	
2411 2435
  public:
2412 2436

	
2413 2437

	
2414 2438
    /// \name Node sections
2415 2439
    /// @{
2416 2440

	
2417 2441
    /// \brief Gives back the number of node sections in the file.
2418 2442
    ///
2419 2443
    /// Gives back the number of node sections in the file.
2420 2444
    int nodeSectionNum() const {
2421 2445
      return _node_sections.size();
2422 2446
    }
2423 2447

	
2424 2448
    /// \brief Returns the node section name at the given position.
2425 2449
    ///
2426 2450
    /// Returns the node section name at the given position.
2427 2451
    const std::string& nodeSection(int i) const {
2428 2452
      return _node_sections[i];
2429 2453
    }
2430 2454

	
2431 2455
    /// \brief Gives back the node maps for the given section.
2432 2456
    ///
2433 2457
    /// Gives back the node maps for the given section.
2434 2458
    const std::vector<std::string>& nodeMapNames(int i) const {
2435 2459
      return _node_maps[i];
2436 2460
    }
2437 2461

	
2438 2462
    /// @}
2439 2463

	
2440 2464
    /// \name Arc/Edge sections
2441 2465
    /// @{
2442 2466

	
2443 2467
    /// \brief Gives back the number of arc/edge sections in the file.
2444 2468
    ///
2445 2469
    /// Gives back the number of arc/edge sections in the file.
2446 2470
    /// \note It is synonym of \c edgeSectionNum().
2447 2471
    int arcSectionNum() const {
2448 2472
      return _edge_sections.size();
2449 2473
    }
2450 2474

	
2451 2475
    /// \brief Returns the arc/edge section name at the given position.
2452 2476
    ///
2453 2477
    /// Returns the arc/edge section name at the given position.
2454 2478
    /// \note It is synonym of \c edgeSection().
2455 2479
    const std::string& arcSection(int i) const {
2456 2480
      return _edge_sections[i];
2457 2481
    }
2458 2482

	
2459 2483
    /// \brief Gives back the arc/edge maps for the given section.
2460 2484
    ///
2461 2485
    /// Gives back the arc/edge maps for the given section.
2462 2486
    /// \note It is synonym of \c edgeMapNames().
2463 2487
    const std::vector<std::string>& arcMapNames(int i) const {
2464 2488
      return _edge_maps[i];
2465 2489
    }
2466 2490

	
2467 2491
    /// @}
2468 2492

	
2469 2493
    /// \name Synonyms
2470 2494
    /// @{
2471 2495

	
2472 2496
    /// \brief Gives back the number of arc/edge sections in the file.
2473 2497
    ///
2474 2498
    /// Gives back the number of arc/edge sections in the file.
2475 2499
    /// \note It is synonym of \c arcSectionNum().
2476 2500
    int edgeSectionNum() const {
2477 2501
      return _edge_sections.size();
2478 2502
    }
2479 2503

	
2480 2504
    /// \brief Returns the section name at the given position.
2481 2505
    ///
2482 2506
    /// Returns the section name at the given position.
2483 2507
    /// \note It is synonym of \c arcSection().
2484 2508
    const std::string& edgeSection(int i) const {
2485 2509
      return _edge_sections[i];
2486 2510
    }
2487 2511

	
2488 2512
    /// \brief Gives back the edge maps for the given section.
2489 2513
    ///
2490 2514
    /// Gives back the edge maps for the given section.
2491 2515
    /// \note It is synonym of \c arcMapNames().
2492 2516
    const std::vector<std::string>& edgeMapNames(int i) const {
2493 2517
      return _edge_maps[i];
2494 2518
    }
Ignore white space 6 line context
... ...
@@ -370,203 +370,209 @@
370 370
  /// This utility writes an \ref lgf-format "LGF" file.
371 371
  ///
372 372
  /// The writing method does a batch processing. The user creates a
373 373
  /// writer object, then various writing rules can be added to the
374 374
  /// writer, and eventually the writing is executed with the \c run()
375 375
  /// member function. A map writing rule can be added to the writer
376 376
  /// with the \c nodeMap() or \c arcMap() members. An optional
377 377
  /// converter parameter can also be added as a standard functor
378 378
  /// converting from the value type of the map to \c std::string. If it
379 379
  /// is set, it will determine how the value type of the map is written to
380 380
  /// the output stream. If the functor is not set, then a default
381 381
  /// conversion will be used. The \c attribute(), \c node() and \c
382 382
  /// arc() functions are used to add attribute writing rules.
383 383
  ///
384 384
  ///\code
385 385
  /// DigraphWriter<Digraph>(digraph, std::cout).
386 386
  ///   nodeMap("coordinates", coord_map).
387 387
  ///   nodeMap("size", size).
388 388
  ///   nodeMap("title", title).
389 389
  ///   arcMap("capacity", cap_map).
390 390
  ///   node("source", src).
391 391
  ///   node("target", trg).
392 392
  ///   attribute("caption", caption).
393 393
  ///   run();
394 394
  ///\endcode
395 395
  ///
396 396
  ///
397 397
  /// By default, the writer does not write additional captions to the
398 398
  /// sections, but they can be give as an optional parameter of
399 399
  /// the \c nodes(), \c arcs() or \c
400 400
  /// attributes() functions.
401 401
  ///
402 402
  /// The \c skipNodes() and \c skipArcs() functions forbid the
403 403
  /// writing of the sections. If two arc sections should be written
404 404
  /// to the output, it can be done in two passes, the first pass
405 405
  /// writes the node section and the first arc section, then the
406 406
  /// second pass skips the node section and writes just the arc
407 407
  /// section to the stream. The output stream can be retrieved with
408 408
  /// the \c ostream() function, hence the second pass can append its
409 409
  /// output to the output of the first pass.
410 410
  template <typename _Digraph>
411 411
  class DigraphWriter {
412 412
  public:
413 413

	
414 414
    typedef _Digraph Digraph;
415 415
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
416 416

	
417 417
  private:
418 418

	
419 419

	
420 420
    std::ostream* _os;
421 421
    bool local_os;
422 422

	
423 423
    const Digraph& _digraph;
424 424

	
425 425
    std::string _nodes_caption;
426 426
    std::string _arcs_caption;
427 427
    std::string _attributes_caption;
428 428

	
429 429
    typedef std::map<Node, std::string> NodeIndex;
430 430
    NodeIndex _node_index;
431 431
    typedef std::map<Arc, std::string> ArcIndex;
432 432
    ArcIndex _arc_index;
433 433

	
434 434
    typedef std::vector<std::pair<std::string,
435 435
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
436 436
    NodeMaps _node_maps;
437 437

	
438 438
    typedef std::vector<std::pair<std::string,
439 439
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
440 440
    ArcMaps _arc_maps;
441 441

	
442 442
    typedef std::vector<std::pair<std::string,
443 443
      _writer_bits::ValueStorageBase*> > Attributes;
444 444
    Attributes _attributes;
445 445

	
446 446
    bool _skip_nodes;
447 447
    bool _skip_arcs;
448 448

	
449 449
  public:
450 450

	
451 451
    /// \brief Constructor
452 452
    ///
453 453
    /// Construct a directed graph writer, which writes to the given
454 454
    /// output stream.
455 455
    DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
456 456
      : _os(&os), local_os(false), _digraph(digraph),
457 457
        _skip_nodes(false), _skip_arcs(false) {}
458 458

	
459 459
    /// \brief Constructor
460 460
    ///
461 461
    /// Construct a directed graph writer, which writes to the given
462 462
    /// output file.
463 463
    DigraphWriter(const Digraph& digraph, const std::string& fn)
464 464
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
465 465
        _skip_nodes(false), _skip_arcs(false) {
466
      if (!(*_os)) throw IoError("Cannot write file", fn);
466
      if (!(*_os)) {
467
        delete _os;
468
        throw IoError("Cannot write file", fn);
469
      }
467 470
    }
468 471

	
469 472
    /// \brief Constructor
470 473
    ///
471 474
    /// Construct a directed graph writer, which writes to the given
472 475
    /// output file.
473 476
    DigraphWriter(const Digraph& digraph, const char* fn)
474 477
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
475 478
        _skip_nodes(false), _skip_arcs(false) {
476
      if (!(*_os)) throw IoError("Cannot write file", fn);
479
      if (!(*_os)) {
480
        delete _os;
481
        throw IoError("Cannot write file", fn);
482
      }
477 483
    }
478 484

	
479 485
    /// \brief Destructor
480 486
    ~DigraphWriter() {
481 487
      for (typename NodeMaps::iterator it = _node_maps.begin();
482 488
           it != _node_maps.end(); ++it) {
483 489
        delete it->second;
484 490
      }
485 491

	
486 492
      for (typename ArcMaps::iterator it = _arc_maps.begin();
487 493
           it != _arc_maps.end(); ++it) {
488 494
        delete it->second;
489 495
      }
490 496

	
491 497
      for (typename Attributes::iterator it = _attributes.begin();
492 498
           it != _attributes.end(); ++it) {
493 499
        delete it->second;
494 500
      }
495 501

	
496 502
      if (local_os) {
497 503
        delete _os;
498 504
      }
499 505
    }
500 506

	
501 507
  private:
502 508

	
503 509
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
504 510
                                                  std::ostream& os);
505 511
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
506 512
                                                  const std::string& fn);
507 513
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
508 514
                                                  const char *fn);
509 515

	
510 516
    DigraphWriter(DigraphWriter& other)
511 517
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
512 518
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
513 519

	
514 520
      other._os = 0;
515 521
      other.local_os = false;
516 522

	
517 523
      _node_index.swap(other._node_index);
518 524
      _arc_index.swap(other._arc_index);
519 525

	
520 526
      _node_maps.swap(other._node_maps);
521 527
      _arc_maps.swap(other._arc_maps);
522 528
      _attributes.swap(other._attributes);
523 529

	
524 530
      _nodes_caption = other._nodes_caption;
525 531
      _arcs_caption = other._arcs_caption;
526 532
      _attributes_caption = other._attributes_caption;
527 533
    }
528 534

	
529 535
    DigraphWriter& operator=(const DigraphWriter&);
530 536

	
531 537
  public:
532 538

	
533 539
    /// \name Writing rules
534 540
    /// @{
535 541

	
536 542
    /// \brief Node map writing rule
537 543
    ///
538 544
    /// Add a node map writing rule to the writer.
539 545
    template <typename Map>
540 546
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
541 547
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
542 548
      _writer_bits::MapStorageBase<Node>* storage =
543 549
        new _writer_bits::MapStorage<Node, Map>(map);
544 550
      _node_maps.push_back(std::make_pair(caption, storage));
545 551
      return *this;
546 552
    }
547 553

	
548 554
    /// \brief Node map writing rule
549 555
    ///
550 556
    /// Add a node map writing rule with specialized converter to the
551 557
    /// writer.
552 558
    template <typename Map, typename Converter>
553 559
    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
554 560
                           const Converter& converter = Converter()) {
555 561
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
556 562
      _writer_bits::MapStorageBase<Node>* storage =
557 563
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
558 564
      _node_maps.push_back(std::make_pair(caption, storage));
559 565
      return *this;
560 566
    }
561 567

	
562 568
    /// \brief Arc map writing rule
563 569
    ///
564 570
    /// Add an arc map writing rule to the writer.
565 571
    template <typename Map>
566 572
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
567 573
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
568 574
      _writer_bits::MapStorageBase<Arc>* storage =
569 575
        new _writer_bits::MapStorage<Arc, Map>(map);
570 576
      _arc_maps.push_back(std::make_pair(caption, storage));
571 577
      return *this;
572 578
    }
... ...
@@ -931,203 +937,209 @@
931 937

	
932 938
  /// \brief Return a \ref DigraphWriter class
933 939
  ///
934 940
  /// This function just returns a \ref DigraphWriter class.
935 941
  /// \relates DigraphWriter
936 942
  template <typename Digraph>
937 943
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
938 944
                                       const char* fn) {
939 945
    DigraphWriter<Digraph> tmp(digraph, fn);
940 946
    return tmp;
941 947
  }
942 948

	
943 949
  template <typename Graph>
944 950
  class GraphWriter;
945 951

	
946 952
  template <typename Graph>
947 953
  GraphWriter<Graph> graphWriter(const Graph& graph,
948 954
                                 std::ostream& os = std::cout);
949 955

	
950 956
  template <typename Graph>
951 957
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn);
952 958

	
953 959
  template <typename Graph>
954 960
  GraphWriter<Graph> graphWriter(const Graph& graph, const char *fn);
955 961

	
956 962
  /// \ingroup lemon_io
957 963
  ///
958 964
  /// \brief \ref lgf-format "LGF" writer for directed graphs
959 965
  ///
960 966
  /// This utility writes an \ref lgf-format "LGF" file.
961 967
  ///
962 968
  /// It can be used almost the same way as \c DigraphWriter.
963 969
  /// The only difference is that this class can handle edges and
964 970
  /// edge maps as well as arcs and arc maps.
965 971
  ///
966 972
  /// The arc maps are written into the file as two columns, the
967 973
  /// caption of the columns are the name of the map prefixed with \c
968 974
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
969 975
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
970 976
  /// of the arc) and the label of corresponding edge.
971 977
  template <typename _Graph>
972 978
  class GraphWriter {
973 979
  public:
974 980

	
975 981
    typedef _Graph Graph;
976 982
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
977 983

	
978 984
  private:
979 985

	
980 986

	
981 987
    std::ostream* _os;
982 988
    bool local_os;
983 989

	
984 990
    const Graph& _graph;
985 991

	
986 992
    std::string _nodes_caption;
987 993
    std::string _edges_caption;
988 994
    std::string _attributes_caption;
989 995

	
990 996
    typedef std::map<Node, std::string> NodeIndex;
991 997
    NodeIndex _node_index;
992 998
    typedef std::map<Edge, std::string> EdgeIndex;
993 999
    EdgeIndex _edge_index;
994 1000

	
995 1001
    typedef std::vector<std::pair<std::string,
996 1002
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
997 1003
    NodeMaps _node_maps;
998 1004

	
999 1005
    typedef std::vector<std::pair<std::string,
1000 1006
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1001 1007
    EdgeMaps _edge_maps;
1002 1008

	
1003 1009
    typedef std::vector<std::pair<std::string,
1004 1010
      _writer_bits::ValueStorageBase*> > Attributes;
1005 1011
    Attributes _attributes;
1006 1012

	
1007 1013
    bool _skip_nodes;
1008 1014
    bool _skip_edges;
1009 1015

	
1010 1016
  public:
1011 1017

	
1012 1018
    /// \brief Constructor
1013 1019
    ///
1014 1020
    /// Construct a directed graph writer, which writes to the given
1015 1021
    /// output stream.
1016 1022
    GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1017 1023
      : _os(&os), local_os(false), _graph(graph),
1018 1024
        _skip_nodes(false), _skip_edges(false) {}
1019 1025

	
1020 1026
    /// \brief Constructor
1021 1027
    ///
1022 1028
    /// Construct a directed graph writer, which writes to the given
1023 1029
    /// output file.
1024 1030
    GraphWriter(const Graph& graph, const std::string& fn)
1025 1031
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1026 1032
        _skip_nodes(false), _skip_edges(false) {
1027
      if (!(*_os)) throw IoError("Cannot write file", fn);
1033
      if (!(*_os)) {
1034
        delete _os;
1035
        throw IoError("Cannot write file", fn);
1036
      }
1028 1037
    }
1029 1038

	
1030 1039
    /// \brief Constructor
1031 1040
    ///
1032 1041
    /// Construct a directed graph writer, which writes to the given
1033 1042
    /// output file.
1034 1043
    GraphWriter(const Graph& graph, const char* fn)
1035 1044
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1036 1045
        _skip_nodes(false), _skip_edges(false) {
1037
      if (!(*_os)) throw IoError("Cannot write file", fn);
1046
      if (!(*_os)) {
1047
        delete _os;
1048
        throw IoError("Cannot write file", fn);
1049
      }
1038 1050
    }
1039 1051

	
1040 1052
    /// \brief Destructor
1041 1053
    ~GraphWriter() {
1042 1054
      for (typename NodeMaps::iterator it = _node_maps.begin();
1043 1055
           it != _node_maps.end(); ++it) {
1044 1056
        delete it->second;
1045 1057
      }
1046 1058

	
1047 1059
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1048 1060
           it != _edge_maps.end(); ++it) {
1049 1061
        delete it->second;
1050 1062
      }
1051 1063

	
1052 1064
      for (typename Attributes::iterator it = _attributes.begin();
1053 1065
           it != _attributes.end(); ++it) {
1054 1066
        delete it->second;
1055 1067
      }
1056 1068

	
1057 1069
      if (local_os) {
1058 1070
        delete _os;
1059 1071
      }
1060 1072
    }
1061 1073

	
1062 1074
  private:
1063 1075

	
1064 1076
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1065 1077
                                            std::ostream& os);
1066 1078
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1067 1079
                                            const std::string& fn);
1068 1080
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1069 1081
                                            const char *fn);
1070 1082

	
1071 1083
    GraphWriter(GraphWriter& other)
1072 1084
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1073 1085
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1074 1086

	
1075 1087
      other._os = 0;
1076 1088
      other.local_os = false;
1077 1089

	
1078 1090
      _node_index.swap(other._node_index);
1079 1091
      _edge_index.swap(other._edge_index);
1080 1092

	
1081 1093
      _node_maps.swap(other._node_maps);
1082 1094
      _edge_maps.swap(other._edge_maps);
1083 1095
      _attributes.swap(other._attributes);
1084 1096

	
1085 1097
      _nodes_caption = other._nodes_caption;
1086 1098
      _edges_caption = other._edges_caption;
1087 1099
      _attributes_caption = other._attributes_caption;
1088 1100
    }
1089 1101

	
1090 1102
    GraphWriter& operator=(const GraphWriter&);
1091 1103

	
1092 1104
  public:
1093 1105

	
1094 1106
    /// \name Writing rules
1095 1107
    /// @{
1096 1108

	
1097 1109
    /// \brief Node map writing rule
1098 1110
    ///
1099 1111
    /// Add a node map writing rule to the writer.
1100 1112
    template <typename Map>
1101 1113
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1102 1114
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1103 1115
      _writer_bits::MapStorageBase<Node>* storage =
1104 1116
        new _writer_bits::MapStorage<Node, Map>(map);
1105 1117
      _node_maps.push_back(std::make_pair(caption, storage));
1106 1118
      return *this;
1107 1119
    }
1108 1120

	
1109 1121
    /// \brief Node map writing rule
1110 1122
    ///
1111 1123
    /// Add a node map writing rule with specialized converter to the
1112 1124
    /// writer.
1113 1125
    template <typename Map, typename Converter>
1114 1126
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
1115 1127
                           const Converter& converter = Converter()) {
1116 1128
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1117 1129
      _writer_bits::MapStorageBase<Node>* storage =
1118 1130
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1119 1131
      _node_maps.push_back(std::make_pair(caption, storage));
1120 1132
      return *this;
1121 1133
    }
1122 1134

	
1123 1135
    /// \brief Edge map writing rule
1124 1136
    ///
1125 1137
    /// Add an edge map writing rule to the writer.
1126 1138
    template <typename Map>
1127 1139
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1128 1140
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1129 1141
      _writer_bits::MapStorageBase<Edge>* storage =
1130 1142
        new _writer_bits::MapStorage<Edge, Map>(map);
1131 1143
      _edge_maps.push_back(std::make_pair(caption, storage));
1132 1144
      return *this;
1133 1145
    }
... ...
@@ -1494,201 +1506,207 @@
1494 1506
      if (!_skip_nodes) {
1495 1507
        writeNodes();
1496 1508
      } else {
1497 1509
        createNodeIndex();
1498 1510
      }
1499 1511
      if (!_skip_edges) {
1500 1512
        writeEdges();
1501 1513
      } else {
1502 1514
        createEdgeIndex();
1503 1515
      }
1504 1516
      writeAttributes();
1505 1517
    }
1506 1518

	
1507 1519
    /// \brief Give back the stream of the writer
1508 1520
    ///
1509 1521
    /// Give back the stream of the writer
1510 1522
    std::ostream& ostream() {
1511 1523
      return *_os;
1512 1524
    }
1513 1525

	
1514 1526
    /// @}
1515 1527
  };
1516 1528

	
1517 1529
  /// \brief Return a \ref GraphWriter class
1518 1530
  ///
1519 1531
  /// This function just returns a \ref GraphWriter class.
1520 1532
  /// \relates GraphWriter
1521 1533
  template <typename Graph>
1522 1534
  GraphWriter<Graph> graphWriter(const Graph& graph,
1523 1535
                                 std::ostream& os = std::cout) {
1524 1536
    GraphWriter<Graph> tmp(graph, os);
1525 1537
    return tmp;
1526 1538
  }
1527 1539

	
1528 1540
  /// \brief Return a \ref GraphWriter class
1529 1541
  ///
1530 1542
  /// This function just returns a \ref GraphWriter class.
1531 1543
  /// \relates GraphWriter
1532 1544
  template <typename Graph>
1533 1545
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
1534 1546
    GraphWriter<Graph> tmp(graph, fn);
1535 1547
    return tmp;
1536 1548
  }
1537 1549

	
1538 1550
  /// \brief Return a \ref GraphWriter class
1539 1551
  ///
1540 1552
  /// This function just returns a \ref GraphWriter class.
1541 1553
  /// \relates GraphWriter
1542 1554
  template <typename Graph>
1543 1555
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
1544 1556
    GraphWriter<Graph> tmp(graph, fn);
1545 1557
    return tmp;
1546 1558
  }
1547 1559

	
1548 1560
  class SectionWriter;
1549 1561

	
1550 1562
  SectionWriter sectionWriter(std::istream& is);
1551 1563
  SectionWriter sectionWriter(const std::string& fn);
1552 1564
  SectionWriter sectionWriter(const char* fn);
1553 1565

	
1554 1566
  /// \ingroup lemon_io
1555 1567
  ///
1556 1568
  /// \brief Section writer class
1557 1569
  ///
1558 1570
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
1559 1571
  /// which contain any data in arbitrary format. Such sections can be
1560 1572
  /// written with this class. A writing rule can be added to the
1561 1573
  /// class with two different functions. With the \c sectionLines()
1562 1574
  /// function a generator can write the section line-by-line, while
1563 1575
  /// with the \c sectionStream() member the section can be written to
1564 1576
  /// an output stream.
1565 1577
  class SectionWriter {
1566 1578
  private:
1567 1579

	
1568 1580
    std::ostream* _os;
1569 1581
    bool local_os;
1570 1582

	
1571 1583
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1572 1584
    Sections;
1573 1585

	
1574 1586
    Sections _sections;
1575 1587

	
1576 1588
  public:
1577 1589

	
1578 1590
    /// \brief Constructor
1579 1591
    ///
1580 1592
    /// Construct a section writer, which writes to the given output
1581 1593
    /// stream.
1582 1594
    SectionWriter(std::ostream& os)
1583 1595
      : _os(&os), local_os(false) {}
1584 1596

	
1585 1597
    /// \brief Constructor
1586 1598
    ///
1587 1599
    /// Construct a section writer, which writes into the given file.
1588 1600
    SectionWriter(const std::string& fn)
1589 1601
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
1590
      if (!(*_os)) throw IoError("Cannot write file", fn);
1602
      if (!(*_os)) {
1603
        delete _os;
1604
        throw IoError("Cannot write file", fn);
1605
      }
1591 1606
    }
1592 1607

	
1593 1608
    /// \brief Constructor
1594 1609
    ///
1595 1610
    /// Construct a section writer, which writes into the given file.
1596 1611
    SectionWriter(const char* fn)
1597 1612
      : _os(new std::ofstream(fn)), local_os(true) {
1598
      if (!(*_os)) throw IoError("Cannot write file", fn);
1613
      if (!(*_os)) {
1614
        delete _os;
1615
        throw IoError("Cannot write file", fn);
1616
      }
1599 1617
    }
1600 1618

	
1601 1619
    /// \brief Destructor
1602 1620
    ~SectionWriter() {
1603 1621
      for (Sections::iterator it = _sections.begin();
1604 1622
           it != _sections.end(); ++it) {
1605 1623
        delete it->second;
1606 1624
      }
1607 1625

	
1608 1626
      if (local_os) {
1609 1627
        delete _os;
1610 1628
      }
1611 1629

	
1612 1630
    }
1613 1631

	
1614 1632
  private:
1615 1633

	
1616 1634
    friend SectionWriter sectionWriter(std::ostream& os);
1617 1635
    friend SectionWriter sectionWriter(const std::string& fn);
1618 1636
    friend SectionWriter sectionWriter(const char* fn);
1619 1637

	
1620 1638
    SectionWriter(SectionWriter& other)
1621 1639
      : _os(other._os), local_os(other.local_os) {
1622 1640

	
1623 1641
      other._os = 0;
1624 1642
      other.local_os = false;
1625 1643

	
1626 1644
      _sections.swap(other._sections);
1627 1645
    }
1628 1646

	
1629 1647
    SectionWriter& operator=(const SectionWriter&);
1630 1648

	
1631 1649
  public:
1632 1650

	
1633 1651
    /// \name Section writers
1634 1652
    /// @{
1635 1653

	
1636 1654
    /// \brief Add a section writer with line oriented writing
1637 1655
    ///
1638 1656
    /// The first parameter is the type descriptor of the section, the
1639 1657
    /// second is a generator with std::string values. At the writing
1640 1658
    /// process, the returned \c std::string will be written into the
1641 1659
    /// output file until it is an empty string.
1642 1660
    ///
1643 1661
    /// For example, an integer vector is written into a section.
1644 1662
    ///\code
1645 1663
    ///  @numbers
1646 1664
    ///  12 45 23 78
1647 1665
    ///  4 28 38 28
1648 1666
    ///  23 6 16
1649 1667
    ///\endcode
1650 1668
    ///
1651 1669
    /// The generator is implemented as a struct.
1652 1670
    ///\code
1653 1671
    ///  struct NumberSection {
1654 1672
    ///    std::vector<int>::const_iterator _it, _end;
1655 1673
    ///    NumberSection(const std::vector<int>& data)
1656 1674
    ///      : _it(data.begin()), _end(data.end()) {}
1657 1675
    ///    std::string operator()() {
1658 1676
    ///      int rem_in_line = 4;
1659 1677
    ///      std::ostringstream ls;
1660 1678
    ///      while (rem_in_line > 0 && _it != _end) {
1661 1679
    ///        ls << *(_it++) << ' ';
1662 1680
    ///        --rem_in_line;
1663 1681
    ///      }
1664 1682
    ///      return ls.str();
1665 1683
    ///    }
1666 1684
    ///  };
1667 1685
    ///
1668 1686
    ///  // ...
1669 1687
    ///
1670 1688
    ///  writer.sectionLines("numbers", NumberSection(vec));
1671 1689
    ///\endcode
1672 1690
    template <typename Functor>
1673 1691
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
1674 1692
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1675 1693
      _sections.push_back(std::make_pair(type,
1676 1694
        new _writer_bits::LineSection<Functor>(functor)));
1677 1695
      return *this;
1678 1696
    }
1679 1697

	
1680 1698

	
1681 1699
    /// \brief Add a section writer with stream oriented writing
1682 1700
    ///
1683 1701
    /// The first parameter is the type of the section, the second is
1684 1702
    /// a functor, which takes a \c std::ostream& parameter. The
1685 1703
    /// functor writes the section to the output stream.
1686 1704
    /// \warning The last line must be closed with end-line character.
1687 1705
    template <typename Functor>
1688 1706
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
1689 1707
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1690 1708
      _sections.push_back(std::make_pair(type,
1691 1709
         new _writer_bits::StreamSection<Functor>(functor)));
1692 1710
      return *this;
1693 1711
    }
1694 1712

	
0 comments (0 inline)