gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Section readers moved to distinct class
0 1 0
default
1 file changed with 248 insertions and 198 deletions:
↑ Collapse diff ↑
Ignore white space 48 line context
... ...
@@ -398,51 +398,49 @@
398 398
  /// member function. A map reading rule can be added to the reader
399 399
  /// with the \c nodeMap() or \c arcMap() members. An optional
400 400
  /// converter parameter can also be added as a standard functor
401 401
  /// converting from std::string to the value type of the map. If it
402 402
  /// is set, it will determine how the tokens in the file should be
403 403
  /// is converted to the map's value type. If the functor is not set,
404 404
  /// then a default conversion will be used. One map can be read into
405 405
  /// multiple map objects at the same time. The \c attribute(), \c
406 406
  /// node() and \c arc() functions are used to add attribute reading
407 407
  /// rules.
408 408
  ///
409 409
  ///\code
410 410
  ///     DigraphReader<Digraph>(std::cin, digraph).
411 411
  ///       nodeMap("coordinates", coord_map).
412 412
  ///       arcMap("capacity", cap_map).
413 413
  ///       node("source", src).
414 414
  ///       node("target", trg).
415 415
  ///       attribute("caption", caption).
416 416
  ///       run();
417 417
  ///\endcode
418 418
  ///
419 419
  /// By default the reader uses the first section in the file of the
420 420
  /// proper type. If a section has an optional name, then it can be
421 421
  /// selected for reading by giving an optional name parameter to the
422
  /// \c nodes(), \c arcs() or \c attributes() functions. The readers
423
  /// also can load extra sections with the \c sectionLines() and
424
  /// sectionStream() functions.
422
  /// \c nodes(), \c arcs() or \c attributes() functions.
425 423
  ///
426 424
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
427 425
  /// that the nodes or arcs should not be constructed (added to the
428 426
  /// graph) during the reading, but instead the label map of the items
429 427
  /// are given as a parameter of these functions. An
430 428
  /// application of these function is multipass reading, which is
431 429
  /// important if two \e \@arcs sections must be read from the
432 430
  /// file. In this example the first phase would read the node set and one
433 431
  /// of the arc sets, while the second phase would read the second arc
434 432
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
435 433
  /// The previously read label node map should be passed to the \c
436 434
  /// useNodes() functions. Another application of multipass reading when
437 435
  /// paths are given as a node map or an arc map. It is impossible read this in
438 436
  /// a single pass, because the arcs are not constructed when the node
439 437
  /// maps are read.
440 438
  template <typename _Digraph>
441 439
  class DigraphReader {
442 440
  public:
443 441

	
444 442
    typedef _Digraph Digraph;
445 443
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
446 444
    
447 445
  private:
448 446

	
... ...
@@ -452,51 +450,48 @@
452 450

	
453 451
    Digraph& _digraph;
454 452

	
455 453
    std::string _nodes_caption;
456 454
    std::string _arcs_caption;
457 455
    std::string _attributes_caption;
458 456

	
459 457
    typedef std::map<std::string, Node> NodeIndex;
460 458
    NodeIndex _node_index;
461 459
    typedef std::map<std::string, Arc> ArcIndex;
462 460
    ArcIndex _arc_index;
463 461
    
464 462
    typedef std::vector<std::pair<std::string, 
465 463
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
466 464
    NodeMaps _node_maps; 
467 465

	
468 466
    typedef std::vector<std::pair<std::string,
469 467
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
470 468
    ArcMaps _arc_maps;
471 469

	
472 470
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
473 471
      Attributes;
474 472
    Attributes _attributes;
475 473

	
476
    typedef std::map<std::string, _reader_bits::Section*> Sections;
477
    Sections _sections;
478

	
479 474
    bool _use_nodes;
480 475
    bool _use_arcs;
481 476

	
482 477
    bool _skip_nodes;
483 478
    bool _skip_arcs;
484 479

	
485 480
    int line_num;
486 481
    std::istringstream line;
487 482

	
488 483
  public:
489 484

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

	
499 494
    /// \brief Constructor
500 495
    ///
501 496
    /// Construct a directed graph reader, which reads from the given
502 497
    /// file.
... ...
@@ -516,73 +511,67 @@
516 511

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

	
526 521
      other._is = 0;
527 522
      other.local_is = false;
528 523
      
529 524
      _node_index.swap(other._node_index);
530 525
      _arc_index.swap(other._arc_index);
531 526

	
532 527
      _node_maps.swap(other._node_maps);
533 528
      _arc_maps.swap(other._arc_maps);
534 529
      _attributes.swap(other._attributes);
535 530

	
536 531
      _nodes_caption = other._nodes_caption;
537 532
      _arcs_caption = other._arcs_caption;
538 533
      _attributes_caption = other._attributes_caption;
539 534

	
540
      _sections.swap(other._sections);
541 535
    }
542 536

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

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

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

	
560
      for (typename Sections::iterator it = _sections.begin(); 
561
	   it != _sections.end(); ++it) {
562
	delete it->second;
563
      }
564

	
565 554
      if (local_is) {
566 555
	delete _is;
567 556
      }
568 557

	
569 558
    }
570 559

	
571 560
  private:
572 561
    
573 562
    DigraphReader& operator=(const DigraphReader&);
574 563

	
575 564
  public:
576 565

	
577 566
    /// \name Reading rules
578 567
    /// @{
579 568
    
580 569
    /// \brief Node map reading rule
581 570
    ///
582 571
    /// Add a node map reading rule to the reader.
583 572
    template <typename Map>
584 573
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
585 574
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
586 575
      _reader_bits::MapStorageBase<Node>* storage = 
587 576
	new _reader_bits::MapStorage<Node, Map>(map);
588 577
      _node_maps.push_back(std::make_pair(caption, storage));
... ...
@@ -687,125 +676,48 @@
687 676
    /// Set \c \@nodes section to be read
688 677
    DigraphReader& nodes(const std::string& caption) {
689 678
      _nodes_caption = caption;
690 679
      return *this;
691 680
    }
692 681

	
693 682
    /// \brief Set \c \@arcs section to be read
694 683
    ///
695 684
    /// Set \c \@arcs section to be read
696 685
    DigraphReader& arcs(const std::string& caption) {
697 686
      _arcs_caption = caption;
698 687
      return *this;
699 688
    }
700 689

	
701 690
    /// \brief Set \c \@attributes section to be read
702 691
    ///
703 692
    /// Set \c \@attributes section to be read
704 693
    DigraphReader& attributes(const std::string& caption) {
705 694
      _attributes_caption = caption;
706 695
      return *this;
707 696
    }
708 697

	
709 698
    /// @}
710 699

	
711
    /// \name Section readers
712
    /// @{
713

	
714
    /// \brief Add a section processor with line oriented reading
715
    ///
716
    /// In the \e LGF file extra sections can be placed, which contain
717
    /// any data in arbitrary format. These sections can be read with
718
    /// this function line by line. The first parameter is the type
719
    /// descriptor of the section, the second is a functor, which
720
    /// takes just one \c std::string parameter. At the reading
721
    /// process, each line of the section will be given to the functor
722
    /// object. However, the empty lines and the comment lines are
723
    /// filtered out, and the leading whitespaces are stipped from
724
    /// each processed string.
725
    ///
726
    /// For example let's see a section, which contain several
727
    /// integers, which should be inserted into a vector.
728
    ///\code
729
    ///  @numbers
730
    ///  12 45 23
731
    ///  4
732
    ///  23 6
733
    ///\endcode
734
    ///
735
    /// The functor is implemented as an struct:
736
    ///\code
737
    ///  struct NumberSection {
738
    ///    std::vector<int>& _data;
739
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
740
    ///    void operator()(const std::string& line) {
741
    ///      std::istringstream ls(line);
742
    ///      int value;
743
    ///      while (ls >> value) _data.push_back(value);
744
    ///    }
745
    ///  };
746
    ///
747
    ///  // ...
748
    ///
749
    ///  reader.sectionLines("numbers", NumberSection(vec));  
750
    ///\endcode
751
    template <typename Functor>
752
    DigraphReader& sectionLines(const std::string& type, Functor functor) {
753
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
754
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
755
		   "Multiple reading of section.");
756
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
757
		   type != "attributes", "Multiple reading of section.");
758
      _sections.insert(std::make_pair(type, 
759
        new _reader_bits::LineSection<Functor>(functor)));
760
      return *this;
761
    }
762

	
763

	
764
    /// \brief Add a section processor with stream oriented reading
765
    ///
766
    /// In the \e LGF file extra sections can be placed, which contain
767
    /// any data in arbitrary format. These sections can be read
768
    /// directly with this function. The first parameter is the type
769
    /// of the section, the second is a functor, which takes an \c
770
    /// std::istream& and an int& parameter, the latter regard to the
771
    /// line number of stream. The functor can read the input while
772
    /// the section go on, and the line number should be modified
773
    /// accordingly.
774
    template <typename Functor>
775
    DigraphReader& sectionStream(const std::string& type, Functor functor) {
776
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
777
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
778
		   "Multiple reading of section.");
779
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
780
		   type != "attributes", "Multiple reading of section.");
781
      _sections.insert(std::make_pair(type, 
782
	 new _reader_bits::StreamSection<Functor>(functor)));
783
      return *this;
784
    }    
785
    
786
    /// @}
787

	
788 700
    /// \name Using previously constructed node or arc set
789 701
    /// @{
790 702

	
791 703
    /// \brief Use previously constructed node set
792 704
    ///
793 705
    /// Use previously constructed node set, and specify the node
794 706
    /// label map.
795 707
    template <typename Map>
796 708
    DigraphReader& useNodes(const Map& map) {
797 709
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
798 710
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
799 711
      _use_nodes = true;
800 712
      _writer_bits::DefaultConverter<typename Map::Value> converter;
801 713
      for (NodeIt n(_digraph); n != INVALID; ++n) {
802 714
	_node_index.insert(std::make_pair(converter(map[n]), n));
803 715
      }
804 716
      return *this;
805 717
    }
806 718

	
807 719
    /// \brief Use previously constructed node set
808 720
    ///
809 721
    /// Use previously constructed node set, and specify the node
810 722
    /// label map and a functor which converts the label map values to
811 723
    /// std::string.
... ...
@@ -1167,92 +1079,81 @@
1167 1079
	  std::ostringstream msg;
1168 1080
	  msg << "Attribute not found in file: " << it->first;
1169 1081
	  throw DataFormatError(msg.str().c_str());
1170 1082
	}	
1171 1083
      }
1172 1084
    }
1173 1085

	
1174 1086
  public:
1175 1087

	
1176 1088
    /// \name Execution of the reader    
1177 1089
    /// @{
1178 1090

	
1179 1091
    /// \brief Start the batch processing
1180 1092
    ///
1181 1093
    /// This function starts the batch processing
1182 1094
    void run() {
1183 1095
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1184 1096
      if (!*_is) {
1185 1097
	throw DataFormatError("Cannot find file");
1186 1098
      }
1187 1099
      
1188 1100
      bool nodes_done = _skip_nodes;
1189 1101
      bool arcs_done = _skip_arcs;
1190 1102
      bool attributes_done = false;
1191
      std::set<std::string> extra_sections;
1192 1103

	
1193 1104
      line_num = 0;      
1194 1105
      readLine();
1195 1106
      skipSection();
1196 1107

	
1197 1108
      while (readSuccess()) {
1198 1109
	try {
1199 1110
	  char c;
1200 1111
	  std::string section, caption;
1201 1112
	  line >> c;
1202 1113
	  _reader_bits::readToken(line, section);
1203 1114
	  _reader_bits::readToken(line, caption);
1204 1115

	
1205 1116
	  if (line >> c) 
1206 1117
	    throw DataFormatError("Extra character on the end of line");
1207 1118

	
1208 1119
	  if (section == "nodes" && !nodes_done) {
1209 1120
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1210 1121
	      readNodes();
1211 1122
	      nodes_done = true;
1212 1123
	    }
1213 1124
	  } else if ((section == "arcs" || section == "edges") && 
1214 1125
		     !arcs_done) {
1215 1126
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
1216 1127
	      readArcs();
1217 1128
	      arcs_done = true;
1218 1129
	    }
1219 1130
	  } else if (section == "attributes" && !attributes_done) {
1220 1131
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1221 1132
	      readAttributes();
1222 1133
	      attributes_done = true;
1223 1134
	    }
1224 1135
	  } else {
1225
	    if (extra_sections.find(section) != extra_sections.end()) {
1226
	      std::ostringstream msg;
1227
	      msg << "Multiple occurence of section " << section;
1228
	      throw DataFormatError(msg.str().c_str());
1229
	    }
1230
	    Sections::iterator it = _sections.find(section);
1231
	    if (it != _sections.end()) {
1232
	      extra_sections.insert(section);
1233
	      it->second->process(*_is, line_num);
1234
	    }
1235 1136
	    readLine();
1236 1137
	    skipSection();
1237 1138
	  }
1238 1139
	} catch (DataFormatError& error) {
1239 1140
	  error.line(line_num);
1240 1141
	  throw;
1241 1142
	}	
1242 1143
      }
1243 1144

	
1244 1145
      if (!nodes_done) {
1245 1146
	throw DataFormatError("Section @nodes not found");
1246 1147
      }
1247 1148

	
1248 1149
      if (!arcs_done) {
1249 1150
	throw DataFormatError("Section @arcs not found");
1250 1151
      }
1251 1152

	
1252 1153
      if (!attributes_done && !_attributes.empty()) {
1253 1154
	throw DataFormatError("Section @attributes not found");
1254 1155
      }
1255 1156

	
1256 1157
    }
1257 1158

	
1258 1159
    /// @}
... ...
@@ -1274,78 +1175,74 @@
1274 1175
    return tmp;
1275 1176
  }
1276 1177

	
1277 1178
  /// \relates DigraphReader
1278 1179
  template <typename Digraph>
1279 1180
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1280 1181
    DigraphReader<Digraph> tmp(fn, digraph);
1281 1182
    return tmp;
1282 1183
  }
1283 1184

	
1284 1185
  /// \ingroup lemon_io
1285 1186
  ///  
1286 1187
  /// \brief LGF reader for undirected graphs
1287 1188
  ///
1288 1189
  /// This utility reads an \ref lgf-format "LGF" file.
1289 1190
  template <typename _Graph>
1290 1191
  class GraphReader {
1291 1192
  public:
1292 1193

	
1293 1194
    typedef _Graph Graph;
1294 1195
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1295 1196
    
1296 1197
  private:
1297 1198

	
1298

	
1299 1199
    std::istream* _is;
1300 1200
    bool local_is;
1301 1201

	
1302 1202
    Graph& _graph;
1303 1203

	
1304 1204
    std::string _nodes_caption;
1305 1205
    std::string _edges_caption;
1306 1206
    std::string _attributes_caption;
1307 1207

	
1308 1208
    typedef std::map<std::string, Node> NodeIndex;
1309 1209
    NodeIndex _node_index;
1310 1210
    typedef std::map<std::string, Edge> EdgeIndex;
1311 1211
    EdgeIndex _edge_index;
1312 1212
    
1313 1213
    typedef std::vector<std::pair<std::string, 
1314 1214
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1315 1215
    NodeMaps _node_maps; 
1316 1216

	
1317 1217
    typedef std::vector<std::pair<std::string,
1318 1218
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1319 1219
    EdgeMaps _edge_maps;
1320 1220

	
1321 1221
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1322 1222
      Attributes;
1323 1223
    Attributes _attributes;
1324 1224

	
1325
    typedef std::map<std::string, _reader_bits::Section*> Sections;
1326
    Sections _sections;
1327

	
1328 1225
    bool _use_nodes;
1329 1226
    bool _use_edges;
1330 1227

	
1331 1228
    bool _skip_nodes;
1332 1229
    bool _skip_edges;
1333 1230

	
1334 1231
    int line_num;
1335 1232
    std::istringstream line;
1336 1233

	
1337 1234
  public:
1338 1235

	
1339 1236
    /// \brief Constructor
1340 1237
    ///
1341 1238
    /// Construct a undirected graph reader, which reads from the given
1342 1239
    /// input stream.
1343 1240
    GraphReader(std::istream& is, Graph& graph) 
1344 1241
      : _is(&is), local_is(false), _graph(graph),
1345 1242
	_use_nodes(false), _use_edges(false),
1346 1243
	_skip_nodes(false), _skip_edges(false) {}
1347 1244

	
1348 1245
    /// \brief Constructor
1349 1246
    ///
1350 1247
    /// Construct a undirected graph reader, which reads from the given
1351 1248
    /// file.
... ...
@@ -1365,73 +1262,67 @@
1365 1262

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

	
1375 1272
      other._is = 0;
1376 1273
      other.local_is = false;
1377 1274
      
1378 1275
      _node_index.swap(other._node_index);
1379 1276
      _edge_index.swap(other._edge_index);
1380 1277

	
1381 1278
      _node_maps.swap(other._node_maps);
1382 1279
      _edge_maps.swap(other._edge_maps);
1383 1280
      _attributes.swap(other._attributes);
1384 1281

	
1385 1282
      _nodes_caption = other._nodes_caption;
1386 1283
      _edges_caption = other._edges_caption;
1387 1284
      _attributes_caption = other._attributes_caption;
1388 1285

	
1389
      _sections.swap(other._sections);
1390 1286
    }
1391 1287

	
1392 1288
    /// \brief Destructor
1393 1289
    ~GraphReader() {
1394 1290
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1395 1291
	   it != _node_maps.end(); ++it) {
1396 1292
	delete it->second;
1397 1293
      }
1398 1294

	
1399 1295
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1400 1296
	   it != _edge_maps.end(); ++it) {
1401 1297
	delete it->second;
1402 1298
      }
1403 1299

	
1404 1300
      for (typename Attributes::iterator it = _attributes.begin(); 
1405 1301
	   it != _attributes.end(); ++it) {
1406 1302
	delete it->second;
1407 1303
      }
1408 1304

	
1409
      for (typename Sections::iterator it = _sections.begin(); 
1410
	   it != _sections.end(); ++it) {
1411
	delete it->second;
1412
      }
1413

	
1414 1305
      if (local_is) {
1415 1306
	delete _is;
1416 1307
      }
1417 1308

	
1418 1309
    }
1419 1310

	
1420 1311
  private:
1421 1312
    
1422 1313
    GraphReader& operator=(const GraphReader&);
1423 1314

	
1424 1315
  public:
1425 1316

	
1426 1317
    /// \name Reading rules
1427 1318
    /// @{
1428 1319
    
1429 1320
    /// \brief Node map reading rule
1430 1321
    ///
1431 1322
    /// Add a node map reading rule to the reader.
1432 1323
    template <typename Map>
1433 1324
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1434 1325
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1435 1326
      _reader_bits::MapStorageBase<Node>* storage = 
1436 1327
	new _reader_bits::MapStorage<Node, Map>(map);
1437 1328
      _node_maps.push_back(std::make_pair(caption, storage));
... ...
@@ -1582,125 +1473,48 @@
1582 1473
    /// Set \c \@nodes section to be read
1583 1474
    GraphReader& nodes(const std::string& caption) {
1584 1475
      _nodes_caption = caption;
1585 1476
      return *this;
1586 1477
    }
1587 1478

	
1588 1479
    /// \brief Set \c \@edges section to be read
1589 1480
    ///
1590 1481
    /// Set \c \@edges section to be read
1591 1482
    GraphReader& edges(const std::string& caption) {
1592 1483
      _edges_caption = caption;
1593 1484
      return *this;
1594 1485
    }
1595 1486

	
1596 1487
    /// \brief Set \c \@attributes section to be read
1597 1488
    ///
1598 1489
    /// Set \c \@attributes section to be read
1599 1490
    GraphReader& attributes(const std::string& caption) {
1600 1491
      _attributes_caption = caption;
1601 1492
      return *this;
1602 1493
    }
1603 1494

	
1604 1495
    /// @}
1605 1496

	
1606
    /// \name Section readers
1607
    /// @{
1608

	
1609
    /// \brief Add a section processor with line oriented reading
1610
    ///
1611
    /// In the \e LGF file extra sections can be placed, which contain
1612
    /// any data in arbitrary format. These sections can be read with
1613
    /// this function line by line. The first parameter is the type
1614
    /// descriptor of the section, the second is a functor, which
1615
    /// takes just one \c std::string parameter. At the reading
1616
    /// process, each line of the section will be given to the functor
1617
    /// object. However, the empty lines and the comment lines are
1618
    /// filtered out, and the leading whitespaces are stipped from
1619
    /// each processed string.
1620
    ///
1621
    /// For example let's see a section, which contain several
1622
    /// integers, which should be inserted into a vector.
1623
    ///\code
1624
    ///  @numbers
1625
    ///  12 45 23
1626
    ///  4
1627
    ///  23 6
1628
    ///\endcode
1629
    ///
1630
    /// The functor is implemented as an struct:
1631
    ///\code
1632
    ///  struct NumberSection {
1633
    ///    std::vector<int>& _data;
1634
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
1635
    ///    void operator()(const std::string& line) {
1636
    ///      std::istringstream ls(line);
1637
    ///      int value;
1638
    ///      while (ls >> value) _data.push_back(value);
1639
    ///    }
1640
    ///  };
1641
    ///
1642
    ///  // ...
1643
    ///
1644
    ///  reader.sectionLines("numbers", NumberSection(vec));  
1645
    ///\endcode
1646
    template <typename Functor>
1647
    GraphReader& sectionLines(const std::string& type, Functor functor) {
1648
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1649
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1650
		   "Multiple reading of section.");
1651
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1652
		   type != "attributes", "Multiple reading of section.");
1653
      _sections.insert(std::make_pair(type, 
1654
        new _reader_bits::LineSection<Functor>(functor)));
1655
      return *this;
1656
    }
1657

	
1658

	
1659
    /// \brief Add a section processor with stream oriented reading
1660
    ///
1661
    /// In the \e LGF file extra sections can be placed, which contain
1662
    /// any data in arbitrary format. These sections can be read
1663
    /// directly with this function. The first parameter is the type
1664
    /// of the section, the second is a functor, which takes an \c
1665
    /// std::istream& and an int& parameter, the latter regard to the
1666
    /// line number of stream. The functor can read the input while
1667
    /// the section go on, and the line number should be modified
1668
    /// accordingly.
1669
    template <typename Functor>
1670
    GraphReader& sectionStream(const std::string& type, Functor functor) {
1671
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1672
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1673
		   "Multiple reading of section.");
1674
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1675
		   type != "attributes", "Multiple reading of section.");
1676
      _sections.insert(std::make_pair(type, 
1677
	 new _reader_bits::StreamSection<Functor>(functor)));
1678
      return *this;
1679
    }    
1680
    
1681
    /// @}
1682

	
1683 1497
    /// \name Using previously constructed node or edge set
1684 1498
    /// @{
1685 1499

	
1686 1500
    /// \brief Use previously constructed node set
1687 1501
    ///
1688 1502
    /// Use previously constructed node set, and specify the node
1689 1503
    /// label map.
1690 1504
    template <typename Map>
1691 1505
    GraphReader& useNodes(const Map& map) {
1692 1506
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1693 1507
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1694 1508
      _use_nodes = true;
1695 1509
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1696 1510
      for (NodeIt n(_graph); n != INVALID; ++n) {
1697 1511
	_node_index.insert(std::make_pair(converter(map[n]), n));
1698 1512
      }
1699 1513
      return *this;
1700 1514
    }
1701 1515

	
1702 1516
    /// \brief Use previously constructed node set
1703 1517
    ///
1704 1518
    /// Use previously constructed node set, and specify the node
1705 1519
    /// label map and a functor which converts the label map values to
1706 1520
    /// std::string.
... ...
@@ -2060,92 +1874,81 @@
2060 1874
	   it != _attributes.end(); ++it) {
2061 1875
	if (read_attr.find(it->first) == read_attr.end()) {
2062 1876
	  std::ostringstream msg;
2063 1877
	  msg << "Attribute not found in file: " << it->first;
2064 1878
	  throw DataFormatError(msg.str().c_str());
2065 1879
	}	
2066 1880
      }
2067 1881
    }
2068 1882

	
2069 1883
  public:
2070 1884

	
2071 1885
    /// \name Execution of the reader    
2072 1886
    /// @{
2073 1887

	
2074 1888
    /// \brief Start the batch processing
2075 1889
    ///
2076 1890
    /// This function starts the batch processing
2077 1891
    void run() {
2078 1892
      
2079 1893
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2080 1894
      
2081 1895
      bool nodes_done = _skip_nodes;
2082 1896
      bool edges_done = _skip_edges;
2083 1897
      bool attributes_done = false;
2084
      std::set<std::string> extra_sections;
2085 1898

	
2086 1899
      line_num = 0;      
2087 1900
      readLine();
2088 1901
      skipSection();
2089 1902

	
2090 1903
      while (readSuccess()) {
2091 1904
	try {
2092 1905
	  char c;
2093 1906
	  std::string section, caption;
2094 1907
	  line >> c;
2095 1908
	  _reader_bits::readToken(line, section);
2096 1909
	  _reader_bits::readToken(line, caption);
2097 1910

	
2098 1911
	  if (line >> c) 
2099 1912
	    throw DataFormatError("Extra character on the end of line");
2100 1913

	
2101 1914
	  if (section == "nodes" && !nodes_done) {
2102 1915
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
2103 1916
	      readNodes();
2104 1917
	      nodes_done = true;
2105 1918
	    }
2106 1919
	  } else if ((section == "edges" || section == "arcs") && 
2107 1920
		     !edges_done) {
2108 1921
	    if (_edges_caption.empty() || _edges_caption == caption) {
2109 1922
	      readEdges();
2110 1923
	      edges_done = true;
2111 1924
	    }
2112 1925
	  } else if (section == "attributes" && !attributes_done) {
2113 1926
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
2114 1927
	      readAttributes();
2115 1928
	      attributes_done = true;
2116 1929
	    }
2117 1930
	  } else {
2118
	    if (extra_sections.find(section) != extra_sections.end()) {
2119
	      std::ostringstream msg;
2120
	      msg << "Multiple occurence of section " << section;
2121
	      throw DataFormatError(msg.str().c_str());
2122
	    }
2123
	    Sections::iterator it = _sections.find(section);
2124
	    if (it != _sections.end()) {
2125
	      extra_sections.insert(section);
2126
	      it->second->process(*_is, line_num);
2127
	    }
2128 1931
	    readLine();
2129 1932
	    skipSection();
2130 1933
	  }
2131 1934
	} catch (DataFormatError& error) {
2132 1935
	  error.line(line_num);
2133 1936
	  throw;
2134 1937
	}	
2135 1938
      }
2136 1939

	
2137 1940
      if (!nodes_done) {
2138 1941
	throw DataFormatError("Section @nodes not found");
2139 1942
      }
2140 1943

	
2141 1944
      if (!edges_done) {
2142 1945
	throw DataFormatError("Section @edges not found");
2143 1946
      }
2144 1947

	
2145 1948
      if (!attributes_done && !_attributes.empty()) {
2146 1949
	throw DataFormatError("Section @attributes not found");
2147 1950
      }
2148 1951

	
2149 1952
    }
2150 1953

	
2151 1954
    /// @}
... ...
@@ -2153,48 +1956,295 @@
2153 1956
  };
2154 1957

	
2155 1958
  /// \relates GraphReader
2156 1959
  template <typename Graph>
2157 1960
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
2158 1961
    GraphReader<Graph> tmp(is, graph);
2159 1962
    return tmp;
2160 1963
  }
2161 1964

	
2162 1965
  /// \relates GraphReader
2163 1966
  template <typename Graph>
2164 1967
  GraphReader<Graph> graphReader(const std::string& fn, 
2165 1968
				       Graph& graph) {
2166 1969
    GraphReader<Graph> tmp(fn, graph);
2167 1970
    return tmp;
2168 1971
  }
2169 1972

	
2170 1973
  /// \relates GraphReader
2171 1974
  template <typename Graph>
2172 1975
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
2173 1976
    GraphReader<Graph> tmp(fn, graph);
2174 1977
    return tmp;
2175 1978
  }
2176 1979

	
1980
  /// \brief Section reader class
1981
  ///
1982
  /// In the \e LGF file extra sections can be placed, which contain
1983
  /// any data in arbitrary format. Such sections can be read with
1984
  /// this class. A reading rule can be added with two different
1985
  /// functions, with the \c sectionLines() function a functor can
1986
  /// process the section line-by-line. While with the \c
1987
  /// sectionStream() member the section can be read from an input
1988
  /// stream.
1989
  class SectionReader {
1990
  private:
1991
    
1992
    std::istream* _is;
1993
    bool local_is;
1994

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

	
1998
    int line_num;
1999
    std::istringstream line;
2000

	
2001
  public:
2002

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

	
2010
    /// \brief Constructor
2011
    ///
2012
    /// Construct a section reader, which reads from the given file.
2013
    SectionReader(const std::string& fn) 
2014
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2015
    
2016
    /// \brief Constructor
2017
    ///
2018
    /// Construct a section reader, which reads from the given file.
2019
    SectionReader(const char* fn) 
2020
      : _is(new std::ifstream(fn)), local_is(true) {}
2021

	
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
    /// \brief Destructor
2036
    ~SectionReader() {
2037
      for (Sections::iterator it = _sections.begin(); 
2038
	   it != _sections.end(); ++it) {
2039
	delete it->second;
2040
      }
2041

	
2042
      if (local_is) {
2043
	delete _is;
2044
      }
2045

	
2046
    }
2047

	
2048
  private:
2049
    
2050
    SectionReader& operator=(const SectionReader&);
2051

	
2052
  public:
2053

	
2054
    /// \name Section readers
2055
    /// @{
2056

	
2057
    /// \brief Add a section processor with line oriented reading
2058
    ///
2059
    /// The first parameter is the type descriptor of the section, the
2060
    /// second is a functor, which takes just one \c std::string
2061
    /// parameter. At the reading process, each line of the section
2062
    /// will be given to the functor object. However, the empty lines
2063
    /// and the comment lines are filtered out, and the leading
2064
    /// whitespaces are trimmed from each processed string.
2065
    ///
2066
    /// For example let's see a section, which contain several
2067
    /// integers, which should be inserted into a vector.
2068
    ///\code
2069
    ///  @numbers
2070
    ///  12 45 23
2071
    ///  4
2072
    ///  23 6
2073
    ///\endcode
2074
    ///
2075
    /// The functor is implemented as an struct:
2076
    ///\code
2077
    ///  struct NumberSection {
2078
    ///    std::vector<int>& _data;
2079
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2080
    ///    void operator()(const std::string& line) {
2081
    ///      std::istringstream ls(line);
2082
    ///      int value;
2083
    ///      while (ls >> value) _data.push_back(value);
2084
    ///    }
2085
    ///  };
2086
    ///
2087
    ///  // ...
2088
    ///
2089
    ///  reader.sectionLines("numbers", NumberSection(vec));  
2090
    ///\endcode
2091
    template <typename Functor>
2092
    SectionReader& sectionLines(const std::string& type, Functor functor) {
2093
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
2094
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2095
		   "Multiple reading of section.");
2096
      _sections.insert(std::make_pair(type, 
2097
        new _reader_bits::LineSection<Functor>(functor)));
2098
      return *this;
2099
    }
2100

	
2101

	
2102
    /// \brief Add a section processor with stream oriented reading
2103
    ///
2104
    /// The first parameter is the type of the section, the second is
2105
    /// a functor, which takes an \c std::istream& and an int&
2106
    /// parameter, the latter regard to the line number of stream. The
2107
    /// functor can read the input while the section go on, and the
2108
    /// line number should be modified accordingly.
2109
    template <typename Functor>
2110
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2111
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
2112
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2113
		   "Multiple reading of section.");
2114
      _sections.insert(std::make_pair(type, 
2115
	 new _reader_bits::StreamSection<Functor>(functor)));
2116
      return *this;
2117
    }    
2118
    
2119
    /// @}
2120

	
2121
  private:
2122

	
2123
    bool readLine() {
2124
      std::string str;
2125
      while(++line_num, std::getline(*_is, str)) {
2126
	line.clear(); line.str(str);
2127
	char c;
2128
	if (line >> std::ws >> c && c != '#') {
2129
	  line.putback(c);
2130
	  return true;
2131
	}
2132
      }
2133
      return false;
2134
    }
2135

	
2136
    bool readSuccess() {
2137
      return static_cast<bool>(*_is);
2138
    }
2139
    
2140
    void skipSection() {
2141
      char c;
2142
      while (readSuccess() && line >> c && c != '@') {
2143
	readLine();
2144
      }
2145
      line.putback(c);
2146
    }
2147

	
2148
  public:
2149

	
2150

	
2151
    /// \name Execution of the reader    
2152
    /// @{
2153

	
2154
    /// \brief Start the batch processing
2155
    ///
2156
    /// This function starts the batch processing
2157
    void run() {
2158
      
2159
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2160
      
2161
      std::set<std::string> extra_sections;
2162

	
2163
      line_num = 0;      
2164
      readLine();
2165
      skipSection();
2166

	
2167
      while (readSuccess()) {
2168
	try {
2169
	  char c;
2170
	  std::string section, caption;
2171
	  line >> c;
2172
	  _reader_bits::readToken(line, section);
2173
	  _reader_bits::readToken(line, caption);
2174

	
2175
	  if (line >> c) 
2176
	    throw DataFormatError("Extra character on the end of line");
2177

	
2178
	  if (extra_sections.find(section) != extra_sections.end()) {
2179
	    std::ostringstream msg;
2180
	    msg << "Multiple occurence of section " << section;
2181
	    throw DataFormatError(msg.str().c_str());
2182
	  }
2183
	  Sections::iterator it = _sections.find(section);
2184
	  if (it != _sections.end()) {
2185
	    extra_sections.insert(section);
2186
	    it->second->process(*_is, line_num);
2187
	  }
2188
	  readLine();
2189
	  skipSection();
2190
	} catch (DataFormatError& error) {
2191
	  error.line(line_num);
2192
	  throw;
2193
	}	
2194
      }
2195
      for (Sections::iterator it = _sections.begin();
2196
	   it != _sections.end(); ++it) {
2197
	if (extra_sections.find(it->first) == extra_sections.end()) {
2198
	  std::ostringstream os;
2199
	  os << "Cannot find section: " << it->first;
2200
	  throw DataFormatError(os.str().c_str());
2201
	}
2202
      }
2203
    }
2204

	
2205
    /// @}
2206
        
2207
  };
2208

	
2209
  /// \relates SectionReader
2210
  inline SectionReader sectionReader(std::istream& is) {
2211
    SectionReader tmp(is);
2212
    return tmp;
2213
  }
2214

	
2215
  /// \relates SectionReader
2216
  inline SectionReader sectionReader(const std::string& fn) {
2217
    SectionReader tmp(fn);
2218
    return tmp;
2219
  }
2220

	
2221
  /// \relates SectionReader
2222
  inline SectionReader sectionReader(const char* fn) {
2223
    SectionReader tmp(fn);
2224
    return tmp;
2225
  }
2226

	
2177 2227
  /// \ingroup lemon_io
2178 2228
  ///
2179 2229
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
2180 2230
  ///
2181 2231
  /// This class can be used to read the sections, the map names and
2182 2232
  /// the attributes from a file. Usually, the Lemon programs know
2183 2233
  /// that, which type of graph, which maps and which attributes
2184 2234
  /// should be read from a file, but in general tools (like glemon)
2185 2235
  /// the contents of an LGF file should be guessed somehow. This class
2186 2236
  /// reads the graph and stores the appropriate information for
2187 2237
  /// reading the graph.
2188 2238
  ///
2189 2239
  ///\code LgfContents contents("graph.lgf"); 
2190 2240
  /// contents.run();
2191 2241
  ///
2192 2242
  /// // does it contain any node section and arc section
2193 2243
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2194 2244
  ///   std::cerr << "Failure, cannot find graph" << std::endl;
2195 2245
  ///   return -1;
2196 2246
  /// }
2197 2247
  /// std::cout << "The name of the default node section : " 
2198 2248
  ///           << contents.nodeSection(0) << std::endl;
2199 2249
  /// std::cout << "The number of the arc maps : " 
2200 2250
  ///           << contents.arcMaps(0).size() << std::endl;
0 comments (0 inline)