00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00020
00021
00022 #ifndef LEMON_LEMON_READER_H
00023 #define LEMON_LEMON_READER_H
00024
00025
00026 #include <iostream>
00027 #include <fstream>
00028 #include <string>
00029 #include <vector>
00030 #include <algorithm>
00031 #include <map>
00032 #include <memory>
00033
00034 #include <lemon/error.h>
00035 #include <lemon/graph_utils.h>
00036 #include <lemon/utility.h>
00037 #include <lemon/bits/item_reader.h>
00038
00039 #include <lemon/concept_check.h>
00040 #include <lemon/concept/maps.h>
00041
00042 namespace lemon {
00043
00044 namespace _reader_bits {
00045
00046 template <typename Item>
00047 class ItemIdReader {
00048 public:
00049
00050 bool isIdReader() { return true; }
00051
00052 void readId(std::istream&, Item&) {}
00053
00054 template <class _ItemIdReader>
00055 struct Constraints {
00056 void constraints() {
00057 bool b = reader.isIdReader();
00058 ignore_unused_variable_warning(b);
00059 Item item;
00060 reader.readId(is, item);
00061 }
00062 _ItemIdReader& reader;
00063 std::istream& is;
00064 };
00065
00066 };
00067
00068 template <typename Item>
00069 class ItemReader {
00070 public:
00071 void read(std::istream&, Item&) {}
00072
00073 template <class _ItemReader>
00074 struct Constraints {
00075 void constraints() {
00076 Item item;
00077 reader.read(is, item);
00078 }
00079 _ItemReader& reader;
00080 std::istream& is;
00081 };
00082
00083 };
00084
00085 template <typename T>
00086 bool operator<(T, T) {
00087 throw DataFormatError("Id is not comparable");
00088 }
00089
00090 template <typename T>
00091 struct Less {
00092 bool operator()(const T& p, const T& q) const {
00093 return p < q;
00094 }
00095 };
00096
00097 template <typename M1, typename M2>
00098 class WriteComposeMap {
00099 public:
00100 typedef True NeedCopy;
00101
00102 typedef typename M2::Key Key;
00103 typedef typename M1::Value Value;
00104
00105 WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
00106 : m1(_m1), m2(_m2) {}
00107
00108 void set(const Key& key, const Value& value) {
00109 m1.set(m2[key], value);
00110 }
00111
00112 private:
00113
00114 typename SmartReference<M1>::Type m1;
00115 typename SmartConstReference<M2>::Type m2;
00116
00117 };
00118
00119 template <typename M1, typename M2>
00120 WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
00121 return WriteComposeMap<M1, M2>(m1, m2);
00122 }
00123
00124 template <typename M1, typename M2>
00125 WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
00126 return WriteComposeMap<M1, M2>(m1, m2);
00127 }
00128
00129 }
00130
00161 class LemonReader {
00162 private:
00163
00164 class FilterStreamBuf : public std::streambuf {
00165 public:
00166
00167 typedef std::streambuf Parent;
00168 typedef Parent::char_type char_type;
00169 FilterStreamBuf(std::istream& is, int& num)
00170 : _is(is), _base(0), _eptr(0),
00171 _num(num), skip_state(after_endl) {}
00172
00173 protected:
00174
00175 enum skip_state_type {
00176 no_skip,
00177 after_endl,
00178 comment_line
00179 };
00180
00181 char_type small_buf[1];
00182
00183
00184 std::istream& _is;
00185
00186 char_type* _base;
00187 char_type* _eptr;
00188
00189 int& _num;
00190
00191 skip_state_type skip_state;
00192
00193
00194 char_type* base() { return _base; }
00195
00196 char_type* eptr() { return _eptr; }
00197
00198 int blen() { return _eptr - _base; }
00199
00200 void setb(char_type* buf, int len) {
00201 _base = buf;
00202 _eptr = buf + len;
00203 }
00204
00205 virtual std::streambuf* setbuf(char *buf, int len) {
00206 if (base()) return 0;
00207 if (buf != 0 && len >= (int)sizeof(small_buf)) {
00208 setb(buf, len);
00209 } else {
00210 setb(small_buf, sizeof(small_buf));
00211 }
00212 setg(0, 0, 0);
00213 return this;
00214 }
00215
00216 bool put_char(char c) {
00217 switch (skip_state) {
00218 case no_skip:
00219 switch (c) {
00220 case '\n':
00221 skip_state = after_endl;
00222 return true;
00223 default:
00224 return true;
00225 }
00226 case after_endl:
00227 switch (c) {
00228 case '@':
00229 return false;
00230 case '\n':
00231 return false;
00232 case '#':
00233 skip_state = comment_line;
00234 return false;
00235 default:
00236 if (!isspace(c)) {
00237 skip_state = no_skip;
00238 return true;
00239 } else {
00240 return false;
00241 }
00242 }
00243 break;
00244 case comment_line:
00245 switch (c) {
00246 case '\n':
00247 skip_state = after_endl;
00248 return false;
00249 default:
00250 return false;
00251 }
00252 }
00253 return false;
00254 }
00255
00256 virtual int underflow() {
00257 char c;
00258 if (_is.read(&c, 1)) {
00259 _is.putback(c);
00260 if (c == '@') {
00261 return EOF;
00262 }
00263 } else {
00264 return EOF;
00265 }
00266 char_type *ptr;
00267 for (ptr = base(); ptr != eptr(); ++ptr) {
00268 if (_is.read(&c, 1)) {
00269 if (c == '\n') ++_num;
00270 if (put_char(c)) {
00271 *ptr = c;
00272 } else {
00273 if (skip_state == after_endl && c == '@') {
00274 _is.putback('@');
00275 break;
00276 }
00277 --ptr;
00278 }
00279 } else {
00280 break;
00281 }
00282 }
00283 setg(base(), base(), ptr);
00284 return *base();
00285 }
00286
00287 virtual int sync() {
00288 return EOF;
00289 }
00290 };
00291
00292 public:
00293
00302 class SectionReader {
00303 friend class LemonReader;
00304 protected:
00309 SectionReader(LemonReader& reader) {
00310 reader.attach(*this);
00311 }
00312
00313 virtual ~SectionReader() {}
00314
00320 virtual bool header(const std::string& line) = 0;
00321
00325 virtual void read(std::istream& is) = 0;
00326 };
00327
00331 LemonReader(std::istream& _is)
00332 : is(&_is), own_is(false) {}
00333
00337 LemonReader(const std::string& filename)
00338 : is(0), own_is(true) {
00339 is = new std::ifstream(filename.c_str());
00340 }
00341
00345 ~LemonReader() {
00346 if (own_is) {
00347 delete is;
00348 }
00349 }
00350
00351 private:
00352 LemonReader(const LemonReader&);
00353 void operator=(const LemonReader&);
00354
00355 void attach(SectionReader& reader) {
00356 readers.push_back(&reader);
00357 }
00358
00359 public:
00363 void run() {
00364 int line_num = 0;
00365 std::string line;
00366 try {
00367 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
00368 SectionReaders::iterator it;
00369 for (it = readers.begin(); it != readers.end(); ++it) {
00370 if ((*it)->header(line)) {
00371 char buf[2048];
00372 FilterStreamBuf buffer(*is, line_num);
00373 buffer.pubsetbuf(buf, sizeof(buf));
00374 std::istream is(&buffer);
00375 (*it)->read(is);
00376 break;
00377 }
00378 }
00379 }
00380 } catch (DataFormatError& error) {
00381 error.line(line_num);
00382 throw error;
00383 }
00384 }
00385
00386
00387 private:
00388
00389 std::istream* is;
00390 bool own_is;
00391
00392 typedef std::vector<SectionReader*> SectionReaders;
00393 SectionReaders readers;
00394
00395 };
00396
00400 class CommonSectionReaderBase : public LemonReader::SectionReader {
00401 typedef LemonReader::SectionReader Parent;
00402 protected:
00403
00408 CommonSectionReaderBase(LemonReader& _reader)
00409 : Parent(_reader) {}
00410
00411 template <typename _Item>
00412 class ReaderBase;
00413
00414 template <typename _Item>
00415 class InverterBase : public ReaderBase<_Item> {
00416 public:
00417 typedef _Item Item;
00418 virtual void read(std::istream&, const Item&) = 0;
00419 virtual Item read(std::istream&) const = 0;
00420
00421 virtual InverterBase<_Item>* getInverter() {
00422 return this;
00423 }
00424 };
00425
00426 template <typename _Item, typename _Map, typename _Reader>
00427 class MapReaderInverter : public InverterBase<_Item> {
00428 public:
00429 typedef _Item Item;
00430 typedef _Reader Reader;
00431 typedef typename Reader::Value Value;
00432 typedef _Map Map;
00433 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
00434
00435 typename SmartReference<Map>::Type map;
00436 Reader reader;
00437 Inverse inverse;
00438
00439 MapReaderInverter(typename SmartParameter<Map>::Type _map,
00440 const Reader& _reader)
00441 : map(_map), reader(_reader) {}
00442
00443 virtual ~MapReaderInverter() {}
00444
00445 virtual void read(std::istream& is, const Item& item) {
00446 Value value;
00447 reader.read(is, value);
00448 map.set(item, value);
00449 typename Inverse::iterator it = inverse.find(value);
00450 if (it == inverse.end()) {
00451 inverse.insert(std::make_pair(value, item));
00452 } else {
00453 throw DataFormatError("Multiple ID occurence");
00454 }
00455 }
00456
00457 virtual Item read(std::istream& is) const {
00458 Value value;
00459 reader.read(is, value);
00460 typename Inverse::const_iterator it = inverse.find(value);
00461 if (it != inverse.end()) {
00462 return it->second;
00463 } else {
00464 throw DataFormatError("Invalid ID error");
00465 }
00466 }
00467 };
00468
00469 template <typename _Item, typename _Reader>
00470 class SkipReaderInverter : public InverterBase<_Item> {
00471 public:
00472 typedef _Item Item;
00473 typedef _Reader Reader;
00474 typedef typename Reader::Value Value;
00475 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
00476
00477 Reader reader;
00478
00479 SkipReaderInverter(const Reader& _reader)
00480 : reader(_reader) {}
00481
00482 virtual ~SkipReaderInverter() {}
00483
00484 virtual void read(std::istream& is, const Item& item) {
00485 Value value;
00486 reader.read(is, value);
00487 typename Inverse::iterator it = inverse.find(value);
00488 if (it == inverse.end()) {
00489 inverse.insert(std::make_pair(value, item));
00490 } else {
00491 throw DataFormatError("Multiple ID occurence error");
00492 }
00493 }
00494
00495 virtual Item read(std::istream& is) const {
00496 Value value;
00497 reader.read(is, value);
00498 typename Inverse::const_iterator it = inverse.find(value);
00499 if (it != inverse.end()) {
00500 return it->second;
00501 } else {
00502 throw DataFormatError("Invalid ID error");
00503 }
00504 }
00505
00506 private:
00507 Inverse inverse;
00508 };
00509
00510 template <typename _Item>
00511 class ReaderBase {
00512 public:
00513 typedef _Item Item;
00514
00515 virtual ~ReaderBase() {}
00516
00517 virtual void read(std::istream& is, const Item& item) = 0;
00518 virtual InverterBase<_Item>* getInverter() = 0;
00519 };
00520
00521 template <typename _Item, typename _Map, typename _Reader>
00522 class MapReader : public ReaderBase<_Item> {
00523 public:
00524 typedef _Map Map;
00525 typedef _Reader Reader;
00526 typedef typename Reader::Value Value;
00527 typedef _Item Item;
00528
00529 typename SmartReference<Map>::Type map;
00530 Reader reader;
00531
00532 MapReader(typename SmartParameter<Map>::Type _map,
00533 const Reader& _reader)
00534 : map(_map), reader(_reader) {}
00535
00536 virtual ~MapReader() {}
00537
00538 virtual void read(std::istream& is, const Item& item) {
00539 Value value;
00540 reader.read(is, value);
00541 map.set(item, value);
00542 }
00543
00544 virtual InverterBase<_Item>* getInverter() {
00545 return new MapReaderInverter<Item, Map, Reader>(map, reader);
00546 }
00547 };
00548
00549
00550 template <typename _Item, typename _Reader>
00551 class SkipReader : public ReaderBase<_Item> {
00552 public:
00553 typedef _Reader Reader;
00554 typedef typename Reader::Value Value;
00555 typedef _Item Item;
00556
00557 Reader reader;
00558 SkipReader(const Reader& _reader) : reader(_reader) {}
00559
00560 virtual ~SkipReader() {}
00561
00562 virtual void read(std::istream& is, const Item&) {
00563 Value value;
00564 reader.read(is, value);
00565 }
00566
00567 virtual InverterBase<Item>* getInverter() {
00568 return new SkipReaderInverter<Item, Reader>(reader);
00569 }
00570 };
00571
00572 template <typename _Item>
00573 class IdReaderBase {
00574 public:
00575 typedef _Item Item;
00576 virtual ~IdReaderBase() {}
00577 virtual Item read(std::istream& is) const = 0;
00578 virtual bool isIdReader() const = 0;
00579 };
00580
00581 template <typename _Item, typename _BoxedIdReader>
00582 class IdReader : public IdReaderBase<_Item> {
00583 public:
00584 typedef _Item Item;
00585 typedef _BoxedIdReader BoxedIdReader;
00586
00587 const BoxedIdReader& boxedIdReader;
00588
00589 IdReader(const BoxedIdReader& _boxedIdReader)
00590 : boxedIdReader(_boxedIdReader) {}
00591
00592 virtual Item read(std::istream& is) const {
00593 Item item;
00594 boxedIdReader.readId(is, item);
00595 return item;
00596 }
00597
00598 virtual bool isIdReader() const {
00599 return boxedIdReader.isIdReader();
00600 }
00601 };
00602
00603 class ValueReaderBase {
00604 public:
00605 virtual void read(std::istream&) {};
00606 virtual ~ValueReaderBase() {}
00607 };
00608
00609 template <typename _Value, typename _Reader>
00610 class ValueReader : public ValueReaderBase {
00611 public:
00612 typedef _Value Value;
00613 typedef _Reader Reader;
00614
00615 ValueReader(Value& _value, const Reader& _reader)
00616 : value(_value), reader(_reader) {}
00617
00618 virtual void read(std::istream& is) {
00619 reader.read(is, value);
00620 }
00621 private:
00622 Value& value;
00623 Reader reader;
00624 };
00625
00626 };
00627
00645 template <typename _Graph, typename _Traits = DefaultReaderTraits>
00646 class NodeSetReader : public CommonSectionReaderBase {
00647 typedef CommonSectionReaderBase Parent;
00648 public:
00649
00650 typedef _Graph Graph;
00651 typedef _Traits Traits;
00652 typedef typename Graph::Node Node;
00653 typedef typename Traits::Skipper DefaultSkipper;
00654
00661 NodeSetReader(LemonReader& _reader,
00662 typename SmartParameter<Graph>::Type _graph,
00663 const std::string& _id = std::string(),
00664 const DefaultSkipper& _skipper = DefaultSkipper())
00665 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
00666
00667
00671 virtual ~NodeSetReader() {
00672 for (typename MapReaders::iterator it = readers.begin();
00673 it != readers.end(); ++it) {
00674 delete it->second;
00675 }
00676 }
00677
00678 private:
00679 NodeSetReader(const NodeSetReader&);
00680 void operator=(const NodeSetReader&);
00681
00682 public:
00683
00687 template <typename Map>
00688 NodeSetReader& readNodeMap(std::string name, Map& map) {
00689 return _readMap<
00690 typename Traits::template Reader<typename Map::Value>, Map,
00691 typename SmartParameter<Map>::Type>(name, map);
00692 }
00693
00694 template <typename Map>
00695 NodeSetReader& readNodeMap(std::string name, const Map& map) {
00696 return _readMap<
00697 typename Traits::template Reader<typename Map::Value>, Map,
00698 typename SmartParameter<Map>::Type>(name, map);
00699 }
00700
00704 template <typename Reader, typename Map>
00705 NodeSetReader& readNodeMap(std::string name, Map& map,
00706 const Reader& reader = Reader()) {
00707 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
00708 (name, map, reader);
00709 }
00710
00711 template <typename Reader, typename Map>
00712 NodeSetReader& readNodeMap(std::string name, const Map& map,
00713 const Reader& reader = Reader()) {
00714 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
00715 (name, map, reader);
00716 }
00717
00718 private:
00719
00720 template <typename Reader, typename Map, typename MapParameter>
00721 NodeSetReader& _readMap(std::string name, MapParameter map,
00722 const Reader& reader = Reader()) {
00723 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
00724 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
00725 if (readers.find(name) != readers.end()) {
00726 ErrorMessage msg;
00727 msg << "Multiple read rule for node map: " << name;
00728 throw IOParameterError(msg.message());
00729 }
00730 readers.insert(
00731 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
00732 return *this;
00733 }
00734
00735 public:
00736
00740 template <typename Reader>
00741 NodeSetReader& skipNodeMap(std::string name,
00742 const Reader& reader = Reader()) {
00743 if (readers.find(name) != readers.end()) {
00744 ErrorMessage msg;
00745 msg << "Multiple read rule for node map: " << name;
00746 throw IOParameterError(msg.message());
00747 }
00748 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
00749 return *this;
00750 }
00751
00752 protected:
00753
00759 virtual bool header(const std::string& line) {
00760 std::istringstream ls(line);
00761 std::string command;
00762 std::string name;
00763 ls >> command >> name;
00764 return command == "@nodeset" && name == id;
00765 }
00766
00770 virtual void read(std::istream& is) {
00771 std::vector<ReaderBase<Node>* > index;
00772 std::string line;
00773
00774 getline(is, line);
00775 std::istringstream ls(line);
00776 while (ls >> id) {
00777 typename MapReaders::iterator it = readers.find(id);
00778 if (it != readers.end()) {
00779 index.push_back(it->second);
00780 } else {
00781 index.push_back(&skipper);
00782 }
00783 if (id == "id" && inverter.get() == 0) {
00784 inverter.reset(index.back()->getInverter());
00785 index.back() = inverter.get();
00786 }
00787 }
00788 while (getline(is, line)) {
00789 Node node = graph.addNode();
00790 std::istringstream ls(line);
00791 for (int i = 0; i < (int)index.size(); ++i) {
00792 index[i]->read(ls, node);
00793 }
00794 }
00795 }
00796
00797 public:
00798
00803 bool isIdReader() const {
00804 return inverter.get() != 0;
00805 }
00806
00811 void readId(std::istream& is, Node& node) const {
00812 node = inverter->read(is);
00813 }
00814
00815 private:
00816
00817 typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
00818 MapReaders readers;
00819
00820 typename SmartReference<Graph>::Type graph;
00821 std::string id;
00822 SkipReader<Node, DefaultSkipper> skipper;
00823
00824 std::auto_ptr<InverterBase<Node> > inverter;
00825 };
00826
00849 template <typename _Graph, typename _Traits = DefaultReaderTraits>
00850 class EdgeSetReader : public CommonSectionReaderBase {
00851 typedef CommonSectionReaderBase Parent;
00852 public:
00853
00854 typedef _Graph Graph;
00855 typedef _Traits Traits;
00856 typedef typename Graph::Node Node;
00857 typedef typename Graph::Edge Edge;
00858 typedef typename Traits::Skipper DefaultSkipper;
00859
00868 template <typename NodeIdReader>
00869 EdgeSetReader(LemonReader& _reader,
00870 typename SmartParameter<Graph>::Type _graph,
00871 const NodeIdReader& _nodeIdReader,
00872 const std::string& _id = std::string(),
00873 const DefaultSkipper& _skipper = DefaultSkipper())
00874 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
00875 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
00876 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
00877 }
00881 virtual ~EdgeSetReader() {
00882 for (typename MapReaders::iterator it = readers.begin();
00883 it != readers.end(); ++it) {
00884 delete it->second;
00885 }
00886 }
00887
00888 private:
00889 EdgeSetReader(const EdgeSetReader&);
00890 void operator=(const EdgeSetReader&);
00891
00892 public:
00893
00897 template <typename Map>
00898 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
00899 return _readMap<
00900 typename Traits::template Reader<typename Map::Value>, Map,
00901 typename SmartParameter<Map>::Type>(name, map);
00902 }
00903
00904 template <typename Map>
00905 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
00906 return _readMap<
00907 typename Traits::template Reader<typename Map::Value>, Map,
00908 typename SmartParameter<Map>::Type>(name, map);
00909 }
00910
00914 template <typename Reader, typename Map>
00915 EdgeSetReader& readEdgeMap(std::string name, Map& map,
00916 const Reader& reader = Reader()) {
00917 return _readMap<Reader, Map,
00918 typename SmartParameter<Map>::Type>(name, map, reader);
00919 }
00920
00921 template <typename Reader, typename Map>
00922 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
00923 const Reader& reader = Reader()) {
00924 return _readMap<Reader, Map,
00925 typename SmartParameter<Map>::Type>(name, map, reader);
00926 }
00927
00928 private:
00929
00930 template <typename Reader, typename Map, typename MapParameter>
00931 EdgeSetReader& _readMap(std::string name, MapParameter map,
00932 const Reader& reader = Reader()) {
00933 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
00934 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
00935 if (readers.find(name) != readers.end()) {
00936 ErrorMessage msg;
00937 msg << "Multiple read rule for edge map: " << name;
00938 throw IOParameterError(msg.message());
00939 }
00940 readers.insert(
00941 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
00942 return *this;
00943 }
00944
00945 public:
00946
00950 template <typename Reader>
00951 EdgeSetReader& skipEdgeMap(std::string name,
00952 const Reader& reader = Reader()) {
00953 if (readers.find(name) != readers.end()) {
00954 ErrorMessage msg;
00955 msg << "Multiple read rule for edge map: " << name;
00956 throw IOParameterError(msg.message());
00957 }
00958 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
00959 return *this;
00960 }
00961
00962 protected:
00963
00969 virtual bool header(const std::string& line) {
00970 std::istringstream ls(line);
00971 std::string command;
00972 std::string name;
00973 ls >> command >> name;
00974 return command == "@edgeset" && name == id;
00975 }
00976
00980 virtual void read(std::istream& is) {
00981 if (!nodeIdReader->isIdReader()) {
00982 throw DataFormatError("Cannot find nodeset or ID map");
00983 }
00984 std::vector<ReaderBase<Edge>* > index;
00985 std::string line;
00986
00987 getline(is, line);
00988 std::istringstream ls(line);
00989 while (ls >> id) {
00990 typename MapReaders::iterator it = readers.find(id);
00991 if (it != readers.end()) {
00992 index.push_back(it->second);
00993 } else {
00994 index.push_back(&skipper);
00995 }
00996 if (id == "id" && inverter.get() == 0) {
00997 inverter.reset(index.back()->getInverter());
00998 index.back() = inverter.get();
00999 }
01000 }
01001 while (getline(is, line)) {
01002 std::istringstream ls(line);
01003 Node from = nodeIdReader->read(ls);
01004 Node to = nodeIdReader->read(ls);
01005 Edge edge = graph.addEdge(from, to);
01006 for (int i = 0; i < (int)index.size(); ++i) {
01007 index[i]->read(ls, edge);
01008 }
01009 }
01010 }
01011
01012 public:
01013
01018 bool isIdReader() const {
01019 return inverter.get() != 0;
01020 }
01021
01026 void readId(std::istream& is, Edge& edge) const {
01027 edge = inverter->read(is);
01028 }
01029
01030 private:
01031
01032 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
01033 MapReaders readers;
01034
01035 typename SmartReference<Graph>::Type graph;
01036 std::string id;
01037 SkipReader<Edge, DefaultSkipper> skipper;
01038
01039 std::auto_ptr<InverterBase<Edge> > inverter;
01040 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
01041 };
01042
01070 template <typename _Graph, typename _Traits = DefaultReaderTraits>
01071 class UndirEdgeSetReader : public CommonSectionReaderBase {
01072 typedef CommonSectionReaderBase Parent;
01073 public:
01074
01075 typedef _Graph Graph;
01076 typedef _Traits Traits;
01077 typedef typename Graph::Node Node;
01078 typedef typename Graph::Edge Edge;
01079 typedef typename Graph::UndirEdge UndirEdge;
01080 typedef typename Traits::Skipper DefaultSkipper;
01081
01090 template <typename NodeIdReader>
01091 UndirEdgeSetReader(LemonReader& _reader,
01092 typename SmartParameter<Graph>::Type _graph,
01093 const NodeIdReader& _nodeIdReader,
01094 const std::string& _id = std::string(),
01095 const DefaultSkipper& _skipper = DefaultSkipper())
01096 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
01097 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
01098 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
01099 }
01103 virtual ~UndirEdgeSetReader() {
01104 for (typename MapReaders::iterator it = readers.begin();
01105 it != readers.end(); ++it) {
01106 delete it->second;
01107 }
01108 }
01109
01110 private:
01111 UndirEdgeSetReader(const UndirEdgeSetReader&);
01112 void operator=(const UndirEdgeSetReader&);
01113
01114 public:
01115
01119 template <typename Map>
01120 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
01121 return _readMap<
01122 typename Traits::template Reader<typename Map::Value>, Map,
01123 typename SmartParameter<Map>::Type>(name, map);
01124 }
01125
01126 template <typename Map>
01127 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
01128 return _readMap<
01129 typename Traits::template Reader<typename Map::Value>, Map,
01130 typename SmartParameter<Map>::Type>(name, map);
01131 }
01132
01136 template <typename Reader, typename Map>
01137 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
01138 const Reader& reader = Reader()) {
01139 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
01140 (name, map, reader);
01141 }
01142
01143 template <typename Reader, typename Map>
01144 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
01145 const Reader& reader = Reader()) {
01146 return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
01147 (name, map, reader);
01148 }
01149
01150 private:
01151
01152 template <typename Reader, typename Map, typename MapParameter>
01153 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
01154 const Reader& reader = Reader()) {
01155 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
01156 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
01157 if (readers.find(name) != readers.end()) {
01158 ErrorMessage msg;
01159 msg << "Multiple read rule for edge map: " << name;
01160 throw IOParameterError(msg.message());
01161 }
01162 readers.insert(
01163 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
01164 return *this;
01165 }
01166
01167 public:
01168
01172 template <typename Reader>
01173 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
01174 const Reader& reader = Reader()) {
01175 if (readers.find(name) != readers.end()) {
01176 ErrorMessage msg;
01177 msg << "Multiple read rule for node map: " << name;
01178 throw IOParameterError(msg.message());
01179 }
01180 readers.insert(make_pair(name,
01181 new SkipReader<UndirEdge, Reader>(reader)));
01182 return *this;
01183 }
01184
01188 template <typename Map>
01189 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
01190 return _readDirMap<
01191 typename Traits::template Reader<typename Map::Value>, Map,
01192 typename SmartParameter<Map>::Type>(name, map);
01193 }
01194
01195 template <typename Map>
01196 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
01197 return _readDirMap<
01198 typename Traits::template Reader<typename Map::Value>, Map,
01199 typename SmartParameter<Map>::Type>(name, map);
01200 }
01201
01205 template <typename Reader, typename Map>
01206 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
01207 const Reader& reader = Reader()) {
01208 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
01209 (name, map, reader);
01210 }
01211
01212 template <typename Reader, typename Map>
01213 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
01214 const Reader& reader = Reader()) {
01215 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
01216 (name, map, reader);
01217 }
01218
01219 private:
01220
01221 template <typename Reader, typename Map, typename MapParameter>
01222 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
01223 const Reader& reader = Reader()) {
01224 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
01225 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
01226 readMap("+" + name,
01227 _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
01228 readMap("-" + name,
01229 _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
01230 return *this;
01231 }
01232
01233 public:
01234
01238 template <typename Reader>
01239 UndirEdgeSetReader& skipEdgeMap(std::string name,
01240 const Reader& reader = Reader()) {
01241 skipMap("+" + name, reader);
01242 skipMap("-" + name, reader);
01243 return *this;
01244 }
01245
01246 protected:
01247
01253 virtual bool header(const std::string& line) {
01254 std::istringstream ls(line);
01255 std::string command;
01256 std::string name;
01257 ls >> command >> name;
01258 return command == "@undiredgeset" && name == id;
01259 }
01260
01264 virtual void read(std::istream& is) {
01265 if (!nodeIdReader->isIdReader()) {
01266 throw DataFormatError("Cannot find nodeset or ID map");
01267 }
01268 std::vector<ReaderBase<UndirEdge>* > index;
01269 std::string line;
01270
01271 getline(is, line);
01272 std::istringstream ls(line);
01273 while (ls >> id) {
01274 typename MapReaders::iterator it = readers.find(id);
01275 if (it != readers.end()) {
01276 index.push_back(it->second);
01277 } else {
01278 index.push_back(&skipper);
01279 }
01280 if (id == "id" && inverter.get() == 0) {
01281 inverter.reset(index.back()->getInverter());
01282 index.back() = inverter.get();
01283 }
01284 }
01285 while (getline(is, line)) {
01286 std::istringstream ls(line);
01287 Node from = nodeIdReader->read(ls);
01288 Node to = nodeIdReader->read(ls);
01289 UndirEdge edge = graph.addEdge(from, to);
01290 for (int i = 0; i < (int)index.size(); ++i) {
01291 index[i]->read(ls, edge);
01292 }
01293 }
01294 }
01295
01296 public:
01297
01302 bool isIdReader() const {
01303 return inverter.get() != 0;
01304 }
01305
01310 void readId(std::istream& is, UndirEdge& undirEdge) const {
01311 undirEdge = inverter->read(is);
01312 }
01313
01320 void readId(std::istream& is, Edge& edge) const {
01321 char c;
01322 is >> c;
01323 UndirEdge undirEdge = inverter->read(is);
01324 if (c == '+') {
01325 edge = graph.direct(undirEdge, true);
01326 } else if (c == '-') {
01327 edge = graph.direct(undirEdge, false);
01328 } else {
01329 throw DataFormatError("Wrong id format for edge "
01330 "in undirected edgeset");
01331 }
01332 }
01333
01334 private:
01335
01336 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
01337 MapReaders readers;
01338
01339 typename SmartReference<Graph>::Type graph;
01340 std::string id;
01341 SkipReader<UndirEdge, DefaultSkipper> skipper;
01342
01343 std::auto_ptr<InverterBase<UndirEdge> > inverter;
01344 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
01345 };
01346
01357 template <typename _Graph>
01358 class NodeReader : public CommonSectionReaderBase {
01359 typedef CommonSectionReaderBase Parent;
01360 typedef _Graph Graph;
01361 typedef typename Graph::Node Node;
01362 public:
01363
01370 template <typename _IdReader>
01371 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
01372 const std::string& _id = std::string())
01373 : Parent(_reader), id(_id) {
01374 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
01375 nodeIdReader.reset(new IdReader<Node, _IdReader>(_idReader));
01376 }
01377
01381 virtual ~NodeReader() {}
01382
01383 private:
01384 NodeReader(const NodeReader&);
01385 void operator=(const NodeReader&);
01386
01387 public:
01388
01392 void readNode(const std::string& name, Node& item) {
01393 if (readers.find(name) != readers.end()) {
01394 ErrorMessage msg;
01395 msg << "Multiple read rule for node: " << name;
01396 throw IOParameterError(msg.message());
01397 }
01398 readers.insert(make_pair(name, &item));
01399 }
01400
01401 protected:
01402
01408 virtual bool header(const std::string& line) {
01409 std::istringstream ls(line);
01410 std::string command;
01411 std::string name;
01412 ls >> command >> name;
01413 return command == "@nodes" && name == id;
01414 }
01415
01419 virtual void read(std::istream& is) {
01420 if (!nodeIdReader->isIdReader()) {
01421 throw DataFormatError("Cannot find nodeset or ID map");
01422 }
01423 std::string line;
01424 while (getline(is, line)) {
01425 std::istringstream ls(line);
01426 std::string id;
01427 ls >> id;
01428 typename NodeReaders::iterator it = readers.find(id);
01429 if (it != readers.end()) {
01430 *(it->second) = nodeIdReader->read(ls);
01431 }
01432 }
01433 }
01434
01435 private:
01436
01437 std::string id;
01438
01439 typedef std::map<std::string, Node*> NodeReaders;
01440 NodeReaders readers;
01441 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
01442 };
01443
01454 template <typename _Graph>
01455 class EdgeReader : public CommonSectionReaderBase {
01456 typedef CommonSectionReaderBase Parent;
01457 typedef _Graph Graph;
01458 typedef typename Graph::Edge Edge;
01459 public:
01460
01467 template <typename _IdReader>
01468 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
01469 const std::string& _id = std::string())
01470 : Parent(_reader), id(_id) {
01471 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
01472 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
01473 }
01474
01478 virtual ~EdgeReader() {}
01479 private:
01480 EdgeReader(const EdgeReader&);
01481 void operator=(const EdgeReader&);
01482
01483 public:
01484
01488 void readEdge(const std::string& name, Edge& item) {
01489 if (readers.find(name) != readers.end()) {
01490 ErrorMessage msg;
01491 msg << "Multiple read rule for edge: " << name;
01492 throw IOParameterError(msg.message());
01493 }
01494 readers.insert(make_pair(name, &item));
01495 }
01496
01497 protected:
01498
01504 virtual bool header(const std::string& line) {
01505 std::istringstream ls(line);
01506 std::string command;
01507 std::string name;
01508 ls >> command >> name;
01509 return command == "@edges" && name == id;
01510 }
01511
01515 virtual void read(std::istream& is) {
01516 if (!edgeIdReader->isIdReader()) {
01517 throw DataFormatError("Cannot find edgeset or ID map");
01518 }
01519 std::string line;
01520 while (getline(is, line)) {
01521 std::istringstream ls(line);
01522 std::string id;
01523 ls >> id;
01524 typename EdgeReaders::iterator it = readers.find(id);
01525 if (it != readers.end()) {
01526 *(it->second) = edgeIdReader->read(ls);
01527 }
01528 }
01529 }
01530
01531 private:
01532
01533 std::string id;
01534
01535 typedef std::map<std::string, Edge*> EdgeReaders;
01536 EdgeReaders readers;
01537 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
01538 };
01539
01550 template <typename _Graph>
01551 class UndirEdgeReader : public CommonSectionReaderBase {
01552 typedef CommonSectionReaderBase Parent;
01553 typedef _Graph Graph;
01554 typedef typename Graph::Edge Edge;
01555 typedef typename Graph::UndirEdge UndirEdge;
01556 public:
01557
01565 template <typename _IdReader>
01566 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
01567 const std::string& _id = std::string())
01568 : Parent(_reader), id(_id) {
01569 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
01570 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
01571 undirEdgeIdReader.reset(new IdReader<UndirEdge, _IdReader>(_idReader));
01572 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
01573 }
01574
01578 virtual ~UndirEdgeReader() {}
01579 private:
01580 UndirEdgeReader(const UndirEdgeReader&);
01581 void operator=(const UndirEdgeReader&);
01582
01583 public:
01584
01588 void readUndirEdge(const std::string& name, UndirEdge& item) {
01589 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
01590 ErrorMessage msg;
01591 msg << "Multiple read rule for undirected edge: " << name;
01592 throw IOParameterError(msg.message());
01593 }
01594 undirEdgeReaders.insert(make_pair(name, &item));
01595 }
01596
01600 void readEdge(const std::string& name, Edge& item) {
01601 if (edgeReaders.find(name) != edgeReaders.end()) {
01602 ErrorMessage msg;
01603 msg << "Multiple read rule for edge: " << name;
01604 throw IOParameterError(msg.message());
01605 }
01606 edgeReaders.insert(make_pair(name, &item));
01607 }
01608
01609 protected:
01610
01616 virtual bool header(const std::string& line) {
01617 std::istringstream ls(line);
01618 std::string command;
01619 std::string name;
01620 ls >> command >> name;
01621 return command == "@undiredges" && name == id;
01622 }
01623
01627 virtual void read(std::istream& is) {
01628 if (!edgeIdReader->isIdReader()) {
01629 throw DataFormatError("Cannot find undirected edgeset or ID map");
01630 }
01631 if (!undirEdgeIdReader->isIdReader()) {
01632 throw DataFormatError("Cannot find undirected edgeset or ID map");
01633 }
01634 std::string line;
01635 while (getline(is, line)) {
01636 std::istringstream ls(line);
01637 std::string id;
01638 ls >> id;
01639 {
01640 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
01641 if (it != undirEdgeReaders.end()) {
01642 *(it->second) = undirEdgeIdReader->read(ls);
01643 break;
01644 }
01645 } {
01646 typename EdgeReaders::iterator it = edgeReaders.find(id);
01647 if (it != edgeReaders.end()) {
01648 *(it->second) = edgeIdReader->read(ls);
01649 break;
01650 }
01651 }
01652 }
01653 }
01654
01655 private:
01656
01657 std::string id;
01658
01659 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
01660 UndirEdgeReaders undirEdgeReaders;
01661 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
01662
01663 typedef std::map<std::string, Edge*> EdgeReaders;
01664 EdgeReaders edgeReaders;
01665 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
01666 };
01667
01679 template <typename _Traits = DefaultReaderTraits>
01680 class AttributeReader : public CommonSectionReaderBase {
01681 typedef CommonSectionReaderBase Parent;
01682 typedef _Traits Traits;
01683 public:
01689 AttributeReader(LemonReader& _reader,
01690 const std::string& _id = std::string())
01691 : Parent(_reader), id(_id) {}
01692
01696 virtual ~AttributeReader() {
01697 for (typename Readers::iterator it = readers.begin();
01698 it != readers.end(); ++it) {
01699 delete it->second;
01700 }
01701 }
01702
01703 private:
01704 AttributeReader(const AttributeReader&);
01705 void operator=(AttributeReader&);
01706
01707 public:
01711 template <typename Value>
01712 AttributeReader& readAttribute(const std::string& id, Value& value) {
01713 return readAttribute<typename Traits::template Reader<Value> >
01714 (id, value);
01715 }
01716
01720 template <typename Reader, typename Value>
01721 AttributeReader& readAttribute(const std::string& name, Value& value,
01722 const Reader& reader = Reader()) {
01723 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
01724 if (readers.find(name) != readers.end()) {
01725 ErrorMessage msg;
01726 msg << "Multiple read rule for attribute: " << name;
01727 throw IOParameterError(msg.message());
01728 }
01729 readers.insert(make_pair(name, new ValueReader<Value, Reader>
01730 (value, reader)));
01731 return *this;
01732 }
01733
01734 protected:
01735
01741 bool header(const std::string& line) {
01742 std::istringstream ls(line);
01743 std::string command;
01744 std::string name;
01745 ls >> command >> name;
01746 return command == "@attributes" && name == id;
01747 }
01748
01752 void read(std::istream& is) {
01753 std::string line;
01754 while (getline(is, line)) {
01755 std::istringstream ls(line);
01756 std::string id;
01757 ls >> id;
01758 typename Readers::iterator it = readers.find(id);
01759 if (it != readers.end()) {
01760 it->second->read(ls);
01761 }
01762 }
01763 }
01764
01765 private:
01766 std::string id;
01767
01768 typedef std::map<std::string, ValueReaderBase*> Readers;
01769 Readers readers;
01770 };
01771
01783 class ContentReader : public LemonReader::SectionReader {
01784 typedef LemonReader::SectionReader Parent;
01785 public:
01789 ContentReader(LemonReader& _reader) : Parent(_reader) {}
01790
01794 virtual ~ContentReader() {}
01795
01799 int nodeSetNum() const {
01800 return nodesets.size();
01801 }
01802
01806 std::string nodeSetName(int index) const {
01807 return nodesets[index].name;
01808 }
01809
01813 const std::vector<std::string>& nodeSetMaps(int index) const {
01814 return nodesets[index].items;
01815 }
01816
01820 int edgeSetNum() const {
01821 return edgesets.size();
01822 }
01823
01827 std::string edgeSetName(int index) const {
01828 return edgesets[index].name;
01829 }
01830
01834 const std::vector<std::string>& edgeSetMaps(int index) const {
01835 return edgesets[index].items;
01836 }
01837
01841 int undirEdgeSetNum() const {
01842 return undiredgesets.size();
01843 }
01844
01849 std::string undirEdgeSetName(int index) const {
01850 return undiredgesets[index].name;
01851 }
01852
01857 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
01858 return undiredgesets[index].items;
01859 }
01860
01864 int nodesNum() const {
01865 return nodes.size();
01866 }
01867
01872 std::string nodesName(int index) const {
01873 return nodes[index].name;
01874 }
01875
01880 const std::vector<std::string>& nodesItems(int index) const {
01881 return nodes[index].items;
01882 }
01883
01887 int edgesNum() const {
01888 return edges.size();
01889 }
01890
01895 std::string edgesName(int index) const {
01896 return edges[index].name;
01897 }
01898
01903 const std::vector<std::string>& edgesItems(int index) const {
01904 return edges[index].items;
01905 }
01906
01911 int undirEdgesNum() const {
01912 return undiredges.size();
01913 }
01914
01920 std::string undirEdgesName(int index) const {
01921 return undiredges[index].name;
01922 }
01923
01929 const std::vector<std::string>& undirEdgesItems(int index) const {
01930 return undiredges[index].items;
01931 }
01932
01933
01937 int attributesNum() const {
01938 return attributes.size();
01939 }
01940
01945 std::string attributesName(int index) const {
01946 return attributes[index].name;
01947 }
01948
01952 const std::vector<std::string>& attributesItems(int index) const {
01953 return attributes[index].items;
01954 }
01955
01956 const std::vector<std::string>& otherSections() const {
01957 return sections;
01958 }
01959
01960 protected:
01961
01966 bool header(const std::string& line) {
01967 std::istringstream ls(line);
01968 std::string command, name;
01969 ls >> command >> name;
01970 if (command == "@nodeset") {
01971 current = command;
01972 nodesets.push_back(SectionInfo(name));
01973 } else if (command == "@edgeset") {
01974 current = command;
01975 edgesets.push_back(SectionInfo(name));
01976 } else if (command == "@undiredgeset") {
01977 current = command;
01978 undiredgesets.push_back(SectionInfo(name));
01979 } else if (command == "@nodes") {
01980 current = command;
01981 nodes.push_back(SectionInfo(name));
01982 } else if (command == "@edges") {
01983 current = command;
01984 edges.push_back(SectionInfo(name));
01985 } else if (command == "@undiredges") {
01986 current = command;
01987 undiredges.push_back(SectionInfo(name));
01988 } else if (command == "@attributes") {
01989 current = command;
01990 attributes.push_back(SectionInfo(name));
01991 } else {
01992 sections.push_back(line);
01993 return false;
01994 }
01995 return true;
01996 }
01997
02001 void read(std::istream& is) {
02002 if (current == "@nodeset") {
02003 readMapNames(is, nodesets.back().items);
02004 } else if (current == "@edgeset") {
02005 readMapNames(is, edgesets.back().items);
02006 } else if (current == "@undiredgeset") {
02007 readMapNames(is, undiredgesets.back().items);
02008 } else if (current == "@nodes") {
02009 readItemNames(is, nodes.back().items);
02010 } else if (current == "@edges") {
02011 readItemNames(is, edges.back().items);
02012 } else if (current == "@undiredges") {
02013 readItemNames(is, undiredges.back().items);
02014 } else if (current == "@attributes") {
02015 readItemNames(is, attributes.back().items);
02016 }
02017 }
02018
02019 private:
02020
02021 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
02022 std::string line, id;
02023 std::getline(is, line);
02024 std::istringstream ls(line);
02025 while (ls >> id) {
02026 maps.push_back(id);
02027 }
02028 while (getline(is, line));
02029 }
02030
02031 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
02032 std::string line, id;
02033 while (std::getline(is, line)) {
02034 std::istringstream ls(line);
02035 ls >> id;
02036 maps.push_back(id);
02037 }
02038 }
02039
02040 struct SectionInfo {
02041 std::string name;
02042 std::vector<std::string> items;
02043
02044 SectionInfo(const std::string& _name) : name(_name) {}
02045 };
02046
02047 std::vector<SectionInfo> nodesets;
02048 std::vector<SectionInfo> edgesets;
02049 std::vector<SectionInfo> undiredgesets;
02050
02051 std::vector<SectionInfo> nodes;
02052 std::vector<SectionInfo> edges;
02053 std::vector<SectionInfo> undiredges;
02054
02055 std::vector<SectionInfo> attributes;
02056
02057 std::vector<std::string> sections;
02058
02059 std::string current;
02060
02061 };
02062
02063 }
02064 #endif