Changeset 1408:892c29484414 in lemon-0.x
- Timestamp:
- 05/09/05 13:24:26 (20 years ago)
- Branch:
- default
- Phase:
- public
- Convert:
- svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1875
- Location:
- src/lemon
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/lemon/Makefile.am
r1402 r1408 53 53 concept_check.h \ 54 54 utility.h \ 55 lemon_reader.h \ 55 56 graph_reader.h \ 56 57 graph_writer.h \ … … 65 66 bits/clearable_graph_extender.h \ 66 67 bits/erasable_graph_extender.h \ 67 bits/undir_graph_extender.h 68 bits/undir_graph_extender.h \ 69 bits/item_reader.h 68 70 69 71 noinst_HEADERS = \ -
src/lemon/graph_reader.h
r1396 r1408 23 23 24 24 #include <iostream> 25 #include <sstream>26 27 #include <map>28 #include <vector>29 30 #include <memory>31 25 32 26 #include <lemon/error.h> 33 27 #include <lemon/lemon_reader.h> 34 28 35 29 namespace lemon { … … 38 32 /// @{ 39 33 40 /// \brief Standard ReaderTraits for the GraphReader class.41 ///42 /// Standard ReaderTraits for the GraphReader class.43 /// It defines standard reading method for all type of value.44 /// \author Balazs Dezso45 struct DefaultReaderTraits {46 47 /// \brief Template class for reading an value.48 ///49 /// Template class for reading an value.50 /// \author Balazs Dezso51 template <typename _Value>52 struct Reader {53 /// The value type.54 typedef _Value Value;55 /// \brief Reads a value from the given stream.56 ///57 /// Reads a value from the given stream.58 void read(std::istream& is, Value& value) {59 if (!(is >> value))60 throw DataFormatError("Default reader format exception");61 }62 };63 64 /// \brief Returns wheter this name is an ID map name.65 ///66 /// Returns wheter this name is an ID map name.67 static bool idMapName(const std::string& name) {68 return name == "id";69 }70 71 /// The reader class for the not needed maps.72 typedef Reader<std::string> DefaultReader;73 74 };75 76 /// \brief Reader class for quoted strings.77 ///78 /// Reader class for quoted strings. It can process the escape79 /// sequences in the string.80 /// \author Balazs Dezso81 class QuotedStringReader {82 public:83 typedef std::string Value;84 85 /// \brief Constructor for the reader.86 ///87 /// Constructor for the reader. If the given parameter is true88 /// the reader processes the escape sequences.89 QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}90 91 /// \brief Reads a quoted string from the given stream.92 ///93 /// Reads a quoted string from the given stream.94 void read(std::istream& is, std::string& value) {95 char c;96 value.clear();97 is >> std::ws;98 if (!is.get(c) || c != '\"')99 throw DataFormatError("Quoted string format error");100 while (is.get(c) && c != '\"') {101 if (escaped && c == '\\') {102 value += readEscape(is);103 } else {104 value += c;105 }106 }107 if (!is) throw DataFormatError("Quoted string format error");108 }109 110 private:111 112 static char readEscape(std::istream& is) {113 char c;114 switch (is.get(c), c) {115 case '\\':116 return '\\';117 case '\"':118 return '\"';119 case '\'':120 return '\'';121 case '\?':122 return '\?';123 case 'a':124 return '\a';125 case 'b':126 return '\b';127 case 'f':128 return '\f';129 case 'n':130 return '\n';131 case 'r':132 return '\r';133 case 't':134 return '\t';135 case 'v':136 return '\v';137 case 'x':138 {139 int code;140 if (!is.get(c) || !isHex(c))141 throw DataFormatError("Escape format error");142 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);143 else code = code * 16 + valueHex(c);144 return code;145 }146 default:147 {148 int code;149 if (!isOct(c))150 throw DataFormatError("Escape format error");151 else if (code = valueOct(c), !is.get(c) || !isOct(c))152 is.putback(c);153 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))154 is.putback(c);155 else code = code * 8 + valueOct(c);156 return code;157 }158 }159 }160 161 static bool isOct(char c) {162 return '0' <= c && c <='7';163 }164 165 static int valueOct(char c) {166 return c - '0';167 }168 169 static bool isHex(char c) {170 return ('0' <= c && c <= '9') ||171 ('a' <= c && c <= 'z') ||172 ('A' <= c && c <= 'Z');173 }174 175 static int valueHex(char c) {176 if ('0' <= c && c <= '9') return c - '0';177 if ('a' <= c && c <= 'z') return c - 'a' + 10;178 return c - 'A' + 10;179 }180 181 bool escaped;182 };183 184 class GUIReader {185 public:186 virtual void read(std::istream& is) = 0;187 };188 189 34 /// \brief The graph reader class. 190 ///191 35 /// 192 36 /// The given file format may contain several maps and labeled nodes or … … 230 74 /// \endcode 231 75 /// 232 /// With \c readNode() and \c readEdge() functions you can read labeled Nodes233 /// and Edges.76 /// With \c readNode() and \c readEdge() functions you can read 77 /// labeled Nodes and Edges. 234 78 /// 235 79 /// \code … … 239 83 /// reader.readEdge("observed", edge); 240 84 /// \endcode 85 /// 86 /// With the \c readAttribute() functions you can read an attribute 87 /// in a variable. You can specify the reader for the attribute as 88 /// the nodemaps. 241 89 /// 242 90 /// After you give all read commands you must call the \c run() member … … 261 109 262 110 typedef _ReaderTraits ReaderTraits; 263 typedef typename ReaderTraits:: DefaultReader DefaultReader;111 typedef typename ReaderTraits::Skipper DefaultSkipper; 264 112 265 113 /// \brief Construct a new GraphReader. … … 268 116 /// and it use the given reader as the default skipper. 269 117 GraphReader(std::istream& _is, Graph& _graph, 270 const DefaultReader& _reader = DefaultReader()) 271 : gui_reader(0), is(_is), graph(_graph), 272 nodeSkipper(_reader), edgeSkipper(_reader) {} 118 const DefaultSkipper& _skipper = DefaultSkipper()) 119 : reader(new LemonReader(_is)), own_reader(true), 120 graph(_graph), skipper(_skipper), 121 nodeset_reader(*reader, graph, std::string(), skipper), 122 edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper), 123 node_reader(*reader, nodeset_reader, std::string()), 124 edge_reader(*reader, edgeset_reader, std::string()), 125 attribute_reader(*reader, std::string()) {} 126 127 /// \brief Construct a new GraphReader. 128 /// 129 /// Construct a new GraphReader. It reads into the given graph 130 /// and it use the given reader as the default skipper. 131 GraphReader(const std::string& _filename, Graph& _graph, 132 const DefaultSkipper& _skipper = DefaultSkipper()) 133 : reader(new LemonReader(_filename)), own_reader(true), 134 graph(_graph), skipper(_skipper), 135 nodeset_reader(*reader, graph, std::string(), skipper), 136 edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper), 137 node_reader(*reader, nodeset_reader, std::string()), 138 edge_reader(*reader, edgeset_reader, std::string()), 139 attribute_reader(*reader, std::string()) {} 140 141 /// \brief Construct a new GraphReader. 142 /// 143 /// Construct a new GraphReader. It reads into the given graph 144 /// and it use the given reader as the default skipper. 145 GraphReader(LemonReader& _reader, Graph& _graph, 146 const DefaultSkipper& _skipper = DefaultSkipper()) 147 : reader(_reader), own_reader(false), 148 graph(_graph), skipper(_skipper), 149 nodeset_reader(*reader, graph, std::string(), skipper), 150 edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper), 151 node_reader(*reader, nodeset_reader, std::string()), 152 edge_reader(*reader, edgeset_reader, std::string()), 153 attribute_reader(*reader, std::string()) {} 273 154 274 155 /// \brief Destruct the graph reader. … … 276 157 /// Destruct the graph reader. 277 158 ~GraphReader() { 278 for (typename NodeMapReaders::iterator it = node_map_readers.begin(); 279 it != node_map_readers.end(); ++it) { 280 delete it->second; 281 } 282 283 for (typename EdgeMapReaders::iterator it = edge_map_readers.begin(); 284 it != edge_map_readers.end(); ++it) { 285 delete it->second; 286 } 287 159 if (own_reader) 160 delete reader; 288 161 } 289 162 … … 293 166 template <typename Map> 294 167 GraphReader& readNodeMap(std::string name, Map& map) { 295 return readNodeMap<typename ReaderTraits::template296 Reader<typename Map::Value>, Map>(name, map);168 nodeset_reader.readMap(name, map); 169 return *this; 297 170 } 298 171 … … 303 176 GraphReader& readNodeMap(std::string name, Map& map, 304 177 const Reader& reader = Reader()) { 305 if (node_map_readers.find(name) != node_map_readers.end()) { 306 ErrorMessage msg; 307 msg << "Multiple read rule for node map: " << name; 308 throw IOParameterError(msg.message()); 309 } 310 node_map_readers.insert( 311 make_pair(name, new MapReader<Node, Map, Reader>(map, reader))); 178 nodeset_reader.readMap(name, map, reader); 312 179 return *this; 313 180 } … … 319 186 GraphReader& skipNodeMap(std::string name, 320 187 const Reader& reader = Reader()) { 321 if (node_map_readers.find(name) != node_map_readers.end()) { 322 ErrorMessage msg; 323 msg << "Multiple read rule for node map: " << name; 324 throw IOParameterError(msg.message()); 325 } 326 node_map_readers.insert( 327 make_pair(name, new SkipReader<Node, Reader>(reader))); 188 nodeset_reader.skipMap(name, reader); 328 189 return *this; 329 190 } … … 334 195 template <typename Map> 335 196 GraphReader& readEdgeMap(std::string name, Map& map) { 336 return readEdgeMap<typename ReaderTraits::template337 Reader<typename Map::Value>, Map>(name, map);197 edgeset_reader.readMap(name, map); 198 return *this; 338 199 } 339 200 … … 345 206 GraphReader& readEdgeMap(std::string name, Map& map, 346 207 const Reader& reader = Reader()) { 347 if (edge_map_readers.find(name) != edge_map_readers.end()) { 348 ErrorMessage msg; 349 msg << "Multiple read rule for edge map: " << name; 350 throw IOParameterError(msg.message()); 351 } 352 edge_map_readers.insert( 353 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader))); 208 edgeset_reader.readMap(name, map, reader); 354 209 return *this; 355 210 } … … 361 216 GraphReader& skipEdgeMap(std::string name, 362 217 const Reader& reader = Reader()) { 363 if (edge_map_readers.find(name) != edge_map_readers.end()) { 364 ErrorMessage msg; 365 msg << "Multiple read rule for edge map: " << name; 366 throw IOParameterError(msg.message()); 367 } 368 edge_map_readers.insert( 369 make_pair(name, new SkipReader<Edge, Reader>(reader))); 218 219 edgeset_reader.skipMap(name, reader); 370 220 return *this; 371 221 } … … 375 225 /// Add a new labeled node reader for the reader. 376 226 GraphReader& readNode(std::string name, Node& node) { 377 if (node_readers.find(name) != node_readers.end()) { 378 ErrorMessage msg; 379 msg << "Multiple read rule for node: " << name; 380 throw IOParameterError(msg.message()); 381 } 382 node_readers.insert(make_pair(name, &node)); 227 node_reader.readNode(name, node); 383 228 return *this; 384 229 } … … 388 233 /// Add a new labeled edge reader for the reader. 389 234 GraphReader& readEdge(std::string name, Edge& edge) { 390 if (edge_readers.find(name) != edge_readers.end()) { 391 ErrorMessage msg; 392 msg << "Multiple read rule for edge: " << name; 393 throw IOParameterError(msg.message()); 394 } 395 edge_readers.insert(make_pair(name, &edge)); 396 return *this; 235 edge_reader.readEdge(name, edge); 236 } 237 238 /// \brief Add a new attribute reader command. 239 /// 240 /// Add a new attribute reader command. 241 template <typename Value> 242 GraphReader& readAttribute(std::string name, Value& value) { 243 attribute_reader.readAttribute(name, value); 244 return *this; 245 } 246 247 /// \brief Add a new attribute reader command. 248 /// 249 /// Add a new attribute reader command. 250 template <typename Reader, typename Value> 251 GraphReader& readAttribute(std::string name, Value& value, 252 const Reader& reader) { 253 attribute_reader.readAttribute<Reader>(name, value, reader); 254 return *this; 255 } 256 257 /// \brief Conversion operator to LemonReader. 258 /// 259 /// Conversion operator to LemonReader. It make possible 260 /// to access the encapsulated \e LemonReader, this way 261 /// you can attach to this reader new instances of 262 /// \e LemonReader::SectionReader. 263 operator LemonReader&() { 264 return *reader; 397 265 } 398 266 … … 401 269 /// Executes the reader commands. 402 270 void run() { 403 int line_num = 0; 404 std::auto_ptr<InverterBase<Node> > nodeInverter; 405 std::auto_ptr<InverterBase<Edge> > edgeInverter; 406 try { 407 std::string line = readNotEmptyLine(is, line_num); 408 if (line.find("@nodeset") == 0) { 409 line = readNodeSet(line_num, nodeInverter); 410 } 411 if (line.find("@edgeset") == 0) { 412 line = readEdgeSet(line_num, edgeInverter, nodeInverter); 413 } 414 if (line.find("@nodes") == 0) { 415 line = readNodes(line_num, nodeInverter); 416 } 417 if (line.find("@edges") == 0) { 418 line = readEdges(line_num, edgeInverter); 419 } 420 if (line.find("@gui") == 0) { 421 line = readGUI(line_num); 422 } 423 if (line.find("@end") != 0) { 424 throw DataFormatError("Invalid control sequence error"); 425 } 426 } catch (DataFormatError e) { 427 e.line(line_num); 428 throw e; 429 } 430 } 431 432 GraphReader& readGUI(GUIReader& reader) { 433 gui_reader = &reader; 434 return *this; 271 reader->run(); 435 272 } 436 273 437 274 private: 438 275 439 template <typename Item> class InverterBase; 440 441 std::string readNodeSet(int& line_num, 442 std::auto_ptr<InverterBase<Node> >& nodeInverter) { 443 std::vector<ReaderBase<Node>* > index; 444 { 445 std::string line = readNotEmptyLine(is, line_num); 446 std::string id; 447 std::istringstream ls(line); 448 while (ls >> id) { 449 typename NodeMapReaders::iterator it = node_map_readers.find(id); 450 if (it != node_map_readers.end()) { 451 index.push_back(it->second); 452 node_map_readers.erase(it); 453 } else { 454 index.push_back(&nodeSkipper); 455 } 456 if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) { 457 nodeInverter.reset(index.back()->getInverter()); 458 index.back() = nodeInverter.get(); 459 } 460 } 461 } 462 463 // if (index.size() == 0) { 464 // throw DataFormatError("Cannot find node id map"); 465 // } 466 467 // nodeInverter = 468 // std::auto_ptr<InverterBase<Node> >(index[0]->getInverter()); 469 std::string line; 470 while (line = readNotEmptyLine(is, line_num), line[0] != '@') { 471 Node node = graph.addNode(); 472 std::istringstream ls(line); 473 for (int i = 0; i < (int)index.size(); ++i) { 474 index[i]->read(ls, node); 475 } 476 } 477 return line; 478 } 479 480 std::string readEdgeSet(int& line_num, 481 std::auto_ptr<InverterBase<Edge> >& edgeInverter, 482 std::auto_ptr<InverterBase<Node> >& nodeInverter) { 483 std::vector<ReaderBase<Edge>*> index; 484 { 485 std::string line = readNotEmptyLine(is, line_num); 486 std::string id; 487 std::istringstream ls(line); 488 while (ls >> id) { 489 typename EdgeMapReaders::iterator it = edge_map_readers.find(id); 490 if (it != edge_map_readers.end()) { 491 index.push_back(it->second); 492 edge_map_readers.erase(it); 493 } else { 494 index.push_back(&edgeSkipper); 495 } 496 if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) { 497 edgeInverter.reset(index.back()->getInverter()); 498 index.back() = edgeInverter.get(); 499 } 500 } 501 } 502 503 if (nodeInverter.get() == 0) { 504 throw DataFormatError("Cannot find node id map"); 505 } 506 // if (index.size() == 0) { 507 // throw DataFormatError("Cannot find edge id map"); 508 // } 509 510 // edgeInverter = 511 // std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter()); 512 std::string line; 513 while (line = readNotEmptyLine(is, line_num), line[0] != '@') { 514 std::istringstream ls(line); 515 Node source = nodeInverter->read(ls); 516 Node target = nodeInverter->read(ls); 517 Edge edge = graph.addEdge(source, target); 518 for (int i = 0; i < (int)index.size(); ++i) { 519 index[i]->read(ls, edge); 520 } 521 } 522 return line; 523 } 524 525 std::string readNodes(int& line_num, 526 std::auto_ptr<InverterBase<Node> >& nodeInverter) { 527 std::string line; 528 if (nodeInverter.get() == 0) { 529 throw DataFormatError("Cannot find node id map"); 530 } 531 while (line = readNotEmptyLine(is, line_num), line[0] != '@') { 532 std::istringstream ls(line); 533 std::string name; 534 ls >> name; 535 typename NodeReaders::iterator it = node_readers.find(name); 536 if (it != node_readers.end()) { 537 *(it -> second) = nodeInverter->read(ls); 538 } 539 } 540 return line; 541 } 542 543 std::string readEdges(int& line_num, 544 std::auto_ptr<InverterBase<Edge> >& edgeInverter) { 545 std::string line; 546 if (edgeInverter.get() == 0) { 547 throw DataFormatError("Cannot find edge id map"); 548 } 549 while (line = readNotEmptyLine(is, line_num), line[0] != '@') { 550 std::istringstream ls(line); 551 std::string name; 552 ls >> name; 553 typename EdgeReaders::iterator it = edge_readers.find(name); 554 if (it != edge_readers.end()) { 555 *(it -> second) = edgeInverter->read(ls); 556 } 557 } 558 return line; 559 } 560 561 std::string readGUI(int& line_num) { 562 std::stringstream section; 563 std::string line; 564 while (line = readNotEmptyLine(is, line_num), line[0] != '@') { 565 section << line << std::endl; 566 } 567 if (gui_reader != 0) { 568 gui_reader->read(section); 569 } 570 return line; 571 } 572 573 std::string readNotEmptyLine(std::istream& is, int& line_num) { 574 std::string line; 575 while (++line_num, getline(is, line)) { 576 int vi = line.find('#'); 577 if (vi != (int)::std::string::npos) { 578 line = line.substr(0, vi); 579 } 580 vi = line.find_first_not_of(" \t"); 581 if (vi != (int)std::string::npos) { 582 return line.substr(vi); 583 } 584 } 585 throw DataFormatError("End of stream error"); 586 } 276 LemonReader* reader; 277 bool own_reader; 278 279 Graph& graph; 280 281 DefaultSkipper skipper; 282 283 NodeSetReader<Graph, ReaderTraits> nodeset_reader; 284 EdgeSetReader<Graph, ReaderTraits> edgeset_reader; 285 286 NodeReader<Graph> node_reader; 287 EdgeReader<Graph> edge_reader; 587 288 588 template <typename _Item> 589 class ReaderBase; 590 591 template <typename _Item> 592 class InverterBase : public ReaderBase<_Item> { 593 public: 594 typedef _Item Item; 595 virtual void read(std::istream&, const Item&) = 0; 596 virtual Item read(std::istream&) = 0; 597 598 virtual InverterBase<_Item>* getInverter() { 599 return this; 600 } 601 }; 602 603 template <typename _Item, typename _Map, typename _Reader> 604 class MapReaderInverter : public InverterBase<_Item> { 605 public: 606 typedef _Item Item; 607 typedef _Reader Reader; 608 typedef typename Reader::Value Value; 609 typedef _Map Map; 610 typedef std::map<Value, Item> Inverse; 611 612 Map& map; 613 Reader reader; 614 Inverse inverse; 615 616 MapReaderInverter(Map& _map, const Reader& _reader) 617 : map(_map), reader(_reader) {} 618 619 virtual ~MapReaderInverter() {} 620 621 virtual void read(std::istream& is, const Item& item) { 622 Value value; 623 reader.read(is, value); 624 map.set(item, value); 625 typename Inverse::iterator it = inverse.find(value); 626 if (it == inverse.end()) { 627 inverse.insert(std::make_pair(value, item)); 628 } else { 629 throw DataFormatError("Multiple ID occurence"); 630 } 631 } 632 633 virtual Item read(std::istream& is) { 634 Value value; 635 reader.read(is, value); 636 typename Inverse::const_iterator it = inverse.find(value); 637 if (it != inverse.end()) { 638 return it->second; 639 } else { 640 throw DataFormatError("Invalid ID error"); 641 } 642 } 643 }; 644 645 template <typename _Item, typename _Reader> 646 class SkipReaderInverter : public InverterBase<_Item> { 647 public: 648 typedef _Item Item; 649 typedef _Reader Reader; 650 typedef typename Reader::Value Value; 651 typedef std::map<Value, Item> Inverse; 652 653 Reader reader; 654 655 SkipReaderInverter(const Reader& _reader) 656 : reader(_reader) {} 657 658 virtual ~SkipReaderInverter() {} 659 660 virtual void read(std::istream& is, const Item& item) { 661 Value value; 662 reader.read(is, value); 663 typename Inverse::iterator it = inverse.find(value); 664 if (it == inverse.end()) { 665 inverse.insert(std::make_pair(value, item)); 666 } else { 667 throw DataFormatError("Multiple ID occurence error"); 668 } 669 } 670 671 virtual Item read(std::istream& is) { 672 Value value; 673 reader.read(is, value); 674 typename Inverse::const_iterator it = inverse.find(value); 675 if (it != inverse.end()) { 676 return it->second; 677 } else { 678 throw DataFormatError("Invalid ID error"); 679 } 680 } 681 private: 682 Inverse inverse; 683 }; 684 685 // Readers 686 687 template <typename _Item> 688 class ReaderBase { 689 public: 690 typedef _Item Item; 691 692 // virtual ~ReaderBase() {} 693 694 virtual void read(std::istream& is, const Item& item) = 0; 695 virtual InverterBase<_Item>* getInverter() = 0; 696 }; 697 698 template <typename _Item, typename _Map, typename _Reader> 699 class MapReader : public ReaderBase<_Item> { 700 public: 701 typedef _Map Map; 702 typedef _Reader Reader; 703 typedef typename Reader::Value Value; 704 typedef _Item Item; 705 706 Map& map; 707 Reader reader; 708 709 MapReader(Map& _map, const Reader& _reader) 710 : map(_map), reader(_reader) {} 711 712 virtual ~MapReader() {} 713 714 virtual void read(std::istream& is, const Item& item) { 715 Value value; 716 reader.read(is, value); 717 map.set(item, value); 718 } 719 720 virtual InverterBase<_Item>* getInverter() { 721 return new MapReaderInverter<Item, Map, Reader>(map, reader); 722 } 723 }; 724 725 726 template <typename _Item, typename _Reader> 727 class SkipReader : public ReaderBase<_Item> { 728 public: 729 typedef _Reader Reader; 730 typedef typename Reader::Value Value; 731 typedef _Item Item; 732 733 Reader reader; 734 SkipReader(const Reader& _reader) : reader(_reader) {} 735 736 virtual ~SkipReader() {} 737 738 virtual void read(std::istream& is, const Item&) { 739 Value value; 740 reader.read(is, value); 741 } 742 743 virtual InverterBase<Item>* getInverter() { 744 return new SkipReaderInverter<Item, Reader>(reader); 745 } 746 }; 747 748 749 typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders; 750 NodeMapReaders node_map_readers; 751 752 typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders; 753 EdgeMapReaders edge_map_readers; 754 755 typedef std::map<std::string, Node*> NodeReaders; 756 NodeReaders node_readers; 757 758 typedef std::map<std::string, Edge*> EdgeReaders; 759 EdgeReaders edge_readers; 760 761 GUIReader* gui_reader; 762 763 std::istream& is; 764 Graph& graph; 765 766 SkipReader<Node, DefaultReader> nodeSkipper; 767 SkipReader<Edge, DefaultReader> edgeSkipper; 768 289 AttributeReader<ReaderTraits> attribute_reader; 769 290 }; 770 291
Note: See TracChangeset
for help on using the changeset viewer.