00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00020
00021 #ifndef LEMON_LEMON_WRITER_H
00022 #define LEMON_LEMON_WRITER_H
00023
00024 #include <iostream>
00025 #include <fstream>
00026 #include <string>
00027 #include <vector>
00028 #include <algorithm>
00029 #include <map>
00030 #include <memory>
00031
00032 #include <lemon/error.h>
00033 #include <lemon/invalid.h>
00034 #include <lemon/graph_utils.h>
00035 #include <lemon/bits/item_writer.h>
00036 #include <lemon/utility.h>
00037 #include <lemon/maps.h>
00038
00039 #include <lemon/concept_check.h>
00040 #include <lemon/concept/maps.h>
00041
00042
00043 namespace lemon {
00044
00045 namespace _writer_bits {
00046
00047 template <typename Item>
00048 class ItemIdWriter {
00049 public:
00050
00051 bool isIdWriter() { return true; }
00052
00053 void writeId(std::ostream&, const Item&) {}
00054
00055 template <class _ItemIdWriter>
00056 struct Constraints {
00057 void constraints() {
00058 bool b = writer.isIdWriter();
00059 ignore_unused_variable_warning(b);
00060 writer.writeId(os, item);
00061 }
00062 _ItemIdWriter& writer;
00063 std::ostream& os;
00064 const Item& item;
00065 };
00066
00067 };
00068
00069 template <typename Item>
00070 class ItemWriter {
00071 public:
00072
00073 void write(std::ostream&, const Item&) {}
00074
00075 template <class _ItemWriter>
00076 struct Constraints {
00077 void constraints() {
00078 writer.write(os, item);
00079 }
00080 _ItemWriter& writer;
00081 std::ostream& os;
00082 const Item& item;
00083 };
00084
00085 };
00086
00087 }
00088
00116 class LemonWriter {
00117 public:
00118
00124 class SectionWriter {
00125 friend class LemonWriter;
00126 protected:
00131 SectionWriter(LemonWriter& writer) {
00132 writer.attach(*this);
00133 }
00134
00135 virtual ~SectionWriter() {}
00136
00140 virtual std::string header() = 0;
00141
00145 virtual void write(std::ostream& os) = 0;
00146 };
00147
00151 LemonWriter(std::ostream& _os)
00152 : os(&_os), own_os(false) {}
00153
00157 LemonWriter(const std::string& filename)
00158 : os(0), own_os(true) {
00159 os = new std::ofstream(filename.c_str());
00160 }
00161
00165 ~LemonWriter() {
00166 if (own_os) {
00167 delete os;
00168 }
00169 }
00170
00171 private:
00172 LemonWriter(const LemonWriter&);
00173 void operator=(const LemonWriter&);
00174
00175 void attach(SectionWriter& writer) {
00176 writers.push_back(&writer);
00177 }
00178
00179 public:
00180
00184 void run() {
00185 SectionWriters::iterator it;
00186 for (it = writers.begin(); it != writers.end(); ++it) {
00187 *os << (*it)->header() << std::endl;
00188 (*it)->write(*os);
00189 }
00190 *os << "@end" << std::endl;
00191 }
00192
00193
00194 private:
00195
00196 std::ostream* os;
00197 bool own_os;
00198
00199 typedef std::vector<SectionWriter*> SectionWriters;
00200 SectionWriters writers;
00201
00202 };
00203
00207 class CommonSectionWriterBase : public LemonWriter::SectionWriter {
00208 typedef LemonWriter::SectionWriter Parent;
00209 protected:
00210
00215 CommonSectionWriterBase(LemonWriter& _writer)
00216 : Parent(_writer) {}
00217
00218 template <typename _Item>
00219 class WriterBase {
00220 public:
00221 typedef _Item Item;
00222
00223 virtual ~WriterBase() {}
00224
00225 virtual void write(std::ostream& os, const Item& item) = 0;
00226 };
00227
00228
00229 template <typename _Item, typename _Map, typename _Writer>
00230 class MapWriter : public WriterBase<_Item> {
00231 public:
00232 typedef _Map Map;
00233 typedef _Writer Writer;
00234 typedef typename Writer::Value Value;
00235 typedef _Item Item;
00236
00237 typename SmartConstReference<Map>::Type map;
00238 Writer writer;
00239
00240 MapWriter(const Map& _map, const Writer& _writer)
00241 : map(_map), writer(_writer) {}
00242
00243 virtual ~MapWriter() {}
00244
00245 virtual void write(std::ostream& os, const Item& item) {
00246 Value value = map[item];
00247 writer.write(os, value);
00248 }
00249
00250 };
00251
00252
00253 class ValueWriterBase {
00254 public:
00255 virtual ~ValueWriterBase() {}
00256 virtual void write(std::ostream&) = 0;
00257 };
00258
00259 template <typename _Value, typename _Writer>
00260 class ValueWriter : public ValueWriterBase {
00261 public:
00262 typedef _Value Value;
00263 typedef _Writer Writer;
00264
00265 ValueWriter(const Value& _value, const Writer& _writer)
00266 : value(_value), writer(_writer) {}
00267
00268 virtual void write(std::ostream& os) {
00269 writer.write(os, value);
00270 }
00271 private:
00272 const Value& value;
00273 Writer writer;
00274 };
00275
00276
00277 template <typename _Item>
00278 class IdWriterBase {
00279 public:
00280 typedef _Item Item;
00281 virtual ~IdWriterBase() {}
00282 virtual void write(std::ostream&, const Item&) const = 0;
00283 virtual bool isIdWriter() const = 0;
00284 };
00285
00286 template <typename _Item, typename _BoxedIdWriter>
00287 class IdWriter : public IdWriterBase<_Item> {
00288 public:
00289 typedef _Item Item;
00290 typedef _BoxedIdWriter BoxedIdWriter;
00291
00292 const BoxedIdWriter& idWriter;
00293
00294 IdWriter(const BoxedIdWriter& _idWriter)
00295 : idWriter(_idWriter) {}
00296
00297 virtual void write(std::ostream& os, const Item& item) const {
00298 idWriter.writeId(os, item);
00299 }
00300
00301 virtual bool isIdWriter() const {
00302 return idWriter.isIdWriter();
00303 }
00304 };
00305 };
00306
00325 template <typename _Graph, typename _Traits = DefaultWriterTraits>
00326 class NodeSetWriter : public CommonSectionWriterBase {
00327 typedef CommonSectionWriterBase Parent;
00328 public:
00329
00330 typedef _Graph Graph;
00331 typedef _Traits Traits;
00332 typedef typename Graph::Node Node;
00333
00340 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
00341 const std::string& _id = std::string(),
00342 bool _forceIdMap = true)
00343 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
00344 graph(_graph), id(_id) {}
00345
00349 virtual ~NodeSetWriter() {
00350 typename MapWriters::iterator it;
00351 for (it = writers.begin(); it != writers.end(); ++it) {
00352 delete it->second;
00353 }
00354 }
00355
00356 private:
00357 NodeSetWriter(const NodeSetWriter&);
00358 void operator=(const NodeSetWriter&);
00359
00360 public:
00361
00365 template <typename Map>
00366 NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
00367 return writeNodeMap<typename Traits::
00368 template Writer<typename Map::Value>, Map>(name, map);
00369 }
00370
00374 template <typename Writer, typename Map>
00375 NodeSetWriter& writeNodeMap(std::string name, const Map& map,
00376 const Writer& writer = Writer()) {
00377 checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
00378 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
00379 writers.push_back(
00380 make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
00381 return *this;
00382 }
00383
00384 protected:
00385
00389 virtual std::string header() {
00390 return "@nodeset " + id;
00391 }
00392
00396 virtual void write(std::ostream& os) {
00397 for (int i = 0; i < (int)writers.size(); ++i) {
00398 if (writers[i].first == "id") {
00399 idMap = writers[i].second;
00400 forceIdMap = false;
00401 break;
00402 }
00403 }
00404 if (forceIdMap) {
00405 os << "id\t";
00406 }
00407 for (int i = 0; i < (int)writers.size(); ++i) {
00408 os << writers[i].first << '\t';
00409 }
00410 os << std::endl;
00411 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
00412 if (forceIdMap) {
00413 os << graph.id(it) << '\t';
00414 }
00415 for (int i = 0; i < (int)writers.size(); ++i) {
00416 writers[i].second->write(os, it);
00417 os << '\t';
00418 }
00419 os << std::endl;
00420 }
00421 }
00422
00423 public:
00424
00430 bool isIdWriter() const {
00431 return idMap != 0 || forceIdMap;
00432 }
00433
00440 void writeId(std::ostream& os, const Node& item) const {
00441 if (forceIdMap) {
00442 os << graph.id(item);
00443 } else {
00444 idMap->write(os, item);
00445 }
00446 }
00447
00448 private:
00449
00450 typedef std::vector<std::pair<std::string, WriterBase<Node>*> > MapWriters;
00451 MapWriters writers;
00452
00453 WriterBase<Node>* idMap;
00454 bool forceIdMap;
00455
00456 typename SmartConstReference<Graph>::Type graph;
00457 std::string id;
00458
00459 };
00460
00484 template <typename _Graph, typename _Traits = DefaultWriterTraits>
00485 class EdgeSetWriter : public CommonSectionWriterBase {
00486 typedef CommonSectionWriterBase Parent;
00487 public:
00488
00489 typedef _Graph Graph;
00490 typedef _Traits Traits;
00491 typedef typename Graph::Node Node;
00492 typedef typename Graph::Edge Edge;
00493
00501 template <typename NodeIdWriter>
00502 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
00503 const NodeIdWriter& _nodeIdWriter,
00504 const std::string& _id = std::string(),
00505 bool _forceIdMap = true)
00506 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
00507 graph(_graph), id(_id) {
00508 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
00509 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
00510 }
00511
00515 virtual ~EdgeSetWriter() {
00516 typename MapWriters::iterator it;
00517 for (it = writers.begin(); it != writers.end(); ++it) {
00518 delete it->second;
00519 }
00520 }
00521
00522 private:
00523 EdgeSetWriter(const EdgeSetWriter&);
00524 void operator=(const EdgeSetWriter&);
00525
00526 public:
00527
00531 template <typename Map>
00532 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
00533 return writeEdgeMap<typename Traits::
00534 template Writer<typename Map::Value>, Map>(name, map);
00535 }
00536
00540 template <typename Writer, typename Map>
00541 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
00542 const Writer& writer = Writer()) {
00543 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
00544 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
00545 writers.push_back(
00546 make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer)));
00547 return *this;
00548 }
00549
00550 protected:
00551
00555 virtual std::string header() {
00556 return "@edgeset " + id;
00557 }
00558
00562 virtual void write(std::ostream& os) {
00563 if (!nodeIdWriter->isIdWriter()) {
00564 throw DataFormatError("Cannot find nodeset or ID map");
00565 }
00566 for (int i = 0; i < (int)writers.size(); ++i) {
00567 if (writers[i].first == "id") {
00568 idMap = writers[i].second;
00569 forceIdMap = false;
00570 break;
00571 }
00572 }
00573 os << "\t\t";
00574 if (forceIdMap) {
00575 os << "id\t";
00576 }
00577 for (int i = 0; i < (int)writers.size(); ++i) {
00578 os << writers[i].first << '\t';
00579 }
00580 os << std::endl;
00581 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
00582 nodeIdWriter->write(os, graph.source(it));
00583 os << '\t';
00584 nodeIdWriter->write(os, graph.target(it));
00585 os << '\t';
00586 if (forceIdMap) {
00587 os << graph.id(it) << '\t';
00588 }
00589 for (int i = 0; i < (int)writers.size(); ++i) {
00590 writers[i].second->write(os, it);
00591 os << '\t';
00592 }
00593 os << std::endl;
00594 }
00595 }
00596
00597 public:
00598
00604 bool isIdWriter() const {
00605 return forceIdMap || idMap != 0;
00606 }
00607
00614 void writeId(std::ostream& os, const Edge& item) const {
00615 if (forceIdMap) {
00616 os << graph.id(item);
00617 } else {
00618 idMap->write(os, item);
00619 }
00620 }
00621
00622 private:
00623
00624 typedef std::vector<std::pair<std::string, WriterBase<Edge>*> > MapWriters;
00625 MapWriters writers;
00626
00627 WriterBase<Edge>* idMap;
00628 bool forceIdMap;
00629
00630 typename SmartConstReference<Graph>::Type graph;
00631 std::string id;
00632
00633 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
00634 };
00635
00665 template <typename _Graph, typename _Traits = DefaultWriterTraits>
00666 class UndirEdgeSetWriter : public CommonSectionWriterBase {
00667 typedef CommonSectionWriterBase Parent;
00668 public:
00669
00670 typedef _Graph Graph;
00671 typedef _Traits Traits;
00672 typedef typename Graph::Node Node;
00673 typedef typename Graph::Edge Edge;
00674 typedef typename Graph::UndirEdge UndirEdge;
00675
00683 template <typename NodeIdWriter>
00684 UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
00685 const NodeIdWriter& _nodeIdWriter,
00686 const std::string& _id = std::string(),
00687 bool _forceIdMap = true)
00688 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
00689 graph(_graph), id(_id) {
00690 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
00691 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
00692 }
00693
00697 virtual ~UndirEdgeSetWriter() {
00698 typename MapWriters::iterator it;
00699 for (it = writers.begin(); it != writers.end(); ++it) {
00700 delete it->second;
00701 }
00702 }
00703
00704 private:
00705 UndirEdgeSetWriter(const UndirEdgeSetWriter&);
00706 void operator=(const UndirEdgeSetWriter&);
00707
00708 public:
00709
00713 template <typename Map>
00714 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
00715 return writeUndirEdgeMap<typename Traits::
00716 template Writer<typename Map::Value>, Map>(name, map);
00717 }
00718
00722 template <typename Writer, typename Map>
00723 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
00724 const Writer& writer = Writer()) {
00725 checkConcept<concept::ReadMap<UndirEdge, typename Map::Value>, Map>();
00726 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
00727 writers.push_back(
00728 make_pair(name, new MapWriter<UndirEdge, Map, Writer>(map, writer)));
00729 return *this;
00730 }
00731
00735 template <typename Map>
00736 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
00737 return writeEdgeMap<typename Traits::
00738 template Writer<typename Map::Value>, Map>(name, map);
00739 }
00740
00744 template <typename Writer, typename Map>
00745 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
00746 const Writer& writer = Writer()) {
00747 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
00748 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
00749 writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
00750 writeUndirEdge("-" + name, composeMap(backwardMap(graph), map), writer);
00751 return *this;
00752 }
00753
00754 protected:
00755
00759 virtual std::string header() {
00760 return "@undiredgeset " + id;
00761 }
00762
00766 virtual void write(std::ostream& os) {
00767 if (!nodeIdWriter->isIdWriter()) {
00768 throw DataFormatError("Cannot find nodeset or ID map");
00769 }
00770 for (int i = 0; i < (int)writers.size(); ++i) {
00771 if (writers[i].first == "id") {
00772 idMap = writers[i].second;
00773 forceIdMap = false;
00774 break;
00775 }
00776 }
00777 os << "\t\t";
00778 if (forceIdMap) {
00779 os << "id\t";
00780 }
00781 for (int i = 0; i < (int)writers.size(); ++i) {
00782 os << writers[i].first << '\t';
00783 }
00784 os << std::endl;
00785 for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
00786 nodeIdWriter->write(os, graph.source(it));
00787 os << '\t';
00788 nodeIdWriter->write(os, graph.target(it));
00789 os << '\t';
00790 if (forceIdMap) {
00791 os << graph.id(it) << '\t';
00792 }
00793 for (int i = 0; i < (int)writers.size(); ++i) {
00794 writers[i].second->write(os, it);
00795 os << '\t';
00796 }
00797 os << std::endl;
00798 }
00799 }
00800
00801 public:
00802
00809 bool isIdWriter() const {
00810 return forceIdMap || idMap != 0;
00811 }
00812
00819 void writeId(std::ostream& os, const UndirEdge& item) const {
00820 if (forceIdMap) {
00821 os << graph.id(item);
00822 } else {
00823 idMap->write(os, item);
00824 }
00825 }
00826
00834 void writeId(std::ostream& os, const Edge& item) const {
00835 if (graph.forward(item)) {
00836 os << "+ ";
00837 } else {
00838 os << "- ";
00839 }
00840 if (forceIdMap) {
00841 os << graph.id(item);
00842 } else {
00843 idMap->write(os, item);
00844 }
00845 }
00846
00847 private:
00848
00849 typedef std::vector<std::pair<std::string,
00850 WriterBase<UndirEdge>*> > MapWriters;
00851 MapWriters writers;
00852
00853 WriterBase<UndirEdge>* idMap;
00854 bool forceIdMap;
00855
00856 typename SmartConstReference<Graph>::Type graph;
00857 std::string id;
00858
00859 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
00860 };
00861
00872 template <typename _Graph>
00873 class NodeWriter : public CommonSectionWriterBase {
00874 typedef CommonSectionWriterBase Parent;
00875 typedef _Graph Graph;
00876 typedef typename Graph::Node Node;
00877 public:
00878
00884 template <typename _IdWriter>
00885 NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
00886 const std::string& _id = std::string())
00887 : Parent(_writer), id(_id) {
00888 checkConcept<_writer_bits::ItemIdWriter<Node>, _IdWriter>();
00889 idWriter.reset(new IdWriter<Node, _IdWriter>(_idWriter));
00890 }
00891
00892
00896 virtual ~NodeWriter() {}
00897
00898 private:
00899 NodeWriter(const NodeWriter&);
00900 void operator=(const NodeWriter&);
00901
00902 public:
00903
00907 void writeNode(const std::string& name, const Node& item) {
00908 writers.push_back(make_pair(name, &item));
00909 }
00910
00911 protected:
00912
00917 virtual std::string header() {
00918 return "@nodes " + id;
00919 }
00920
00924 virtual void write(std::ostream& os) {
00925 if (!idWriter->isIdWriter()) {
00926 throw DataFormatError("Cannot find nodeset or ID map");
00927 }
00928 for (int i = 0; i < (int)writers.size(); ++i) {
00929 os << writers[i].first << ' ';
00930 idWriter->write(os, *(writers[i].second));
00931 os << std::endl;
00932 }
00933 }
00934
00935 private:
00936
00937 std::string id;
00938
00939 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
00940 NodeWriters writers;
00941 std::auto_ptr<IdWriterBase<Node> > idWriter;
00942 };
00943
00954 template <typename _Graph>
00955 class EdgeWriter : public CommonSectionWriterBase {
00956 typedef CommonSectionWriterBase Parent;
00957 typedef _Graph Graph;
00958 typedef typename Graph::Edge Edge;
00959 public:
00960
00966 template <typename _IdWriter>
00967 EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
00968 const std::string& _id = std::string())
00969 : Parent(_writer), id(_id) {
00970 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
00971 idWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
00972 }
00973
00977 virtual ~EdgeWriter() {}
00978 private:
00979 EdgeWriter(const EdgeWriter&);
00980 void operator=(const EdgeWriter&);
00981
00982 public:
00983
00987 void writeEdge(const std::string& name, const Edge& item) {
00988 writers.push_back(make_pair(name, &item));
00989 }
00990
00991 protected:
00992
00997 virtual std::string header() {
00998 return "@edges " + id;
00999 }
01000
01004 virtual void write(std::ostream& os) {
01005 if (!idWriter->isIdWriter()) {
01006 throw DataFormatError("Cannot find edgeset or ID map");
01007 }
01008 for (int i = 0; i < (int)writers.size(); ++i) {
01009 os << writers[i].first << ' ';
01010 idWriter->write(os, *(writers[i].second));
01011 os << std::endl;
01012 }
01013 }
01014
01015 private:
01016
01017 std::string id;
01018
01019 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
01020 EdgeWriters writers;
01021
01022 std::auto_ptr<IdWriterBase<Edge> > idWriter;
01023 };
01024
01035 template <typename _Graph>
01036 class UndirEdgeWriter : public CommonSectionWriterBase {
01037 typedef CommonSectionWriterBase Parent;
01038 typedef _Graph Graph;
01039 typedef typename Graph::Node Node;
01040 typedef typename Graph::Edge Edge;
01041 typedef typename Graph::UndirEdge UndirEdge;
01042 public:
01043
01050 template <typename _IdWriter>
01051 UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
01052 const std::string& _id = std::string())
01053 : Parent(_writer), id(_id) {
01054 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
01055 checkConcept<_writer_bits::ItemIdWriter<UndirEdge>, _IdWriter>();
01056 undirEdgeIdWriter.reset(new IdWriter<UndirEdge, _IdWriter>(_idWriter));
01057 edgeIdWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
01058 }
01059
01063 virtual ~UndirEdgeWriter() {}
01064 private:
01065 UndirEdgeWriter(const UndirEdgeWriter&);
01066 void operator=(const UndirEdgeWriter&);
01067
01068 public:
01069
01073 void writeEdge(const std::string& name, const Edge& item) {
01074 edgeWriters.push_back(make_pair(name, &item));
01075 }
01076
01080 void writeUndirEdge(const std::string& name, const UndirEdge& item) {
01081 undirEdgeWriters.push_back(make_pair(name, &item));
01082 }
01083
01084 protected:
01085
01090 virtual std::string header() {
01091 return "@undiredges " + id;
01092 }
01093
01097 virtual void write(std::ostream& os) {
01098 if (!edgeIdWriter->isIdWriter()) {
01099 throw DataFormatError("Cannot find undirected edgeset or ID map");
01100 }
01101 if (!undirEdgeIdWriter->isIdWriter()) {
01102 throw DataFormatError("Cannot find undirected edgeset or ID map");
01103 }
01104 for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) {
01105 os << undirEdgeWriters[i].first << ' ';
01106 undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second));
01107 os << std::endl;
01108 }
01109 for (int i = 0; i < (int)edgeWriters.size(); ++i) {
01110 os << edgeWriters[i].first << ' ';
01111 edgeIdWriter->write(os, *(edgeWriters[i].second));
01112 os << std::endl;
01113 }
01114 }
01115
01116 private:
01117
01118 std::string id;
01119
01120 typedef std::vector<std::pair<std::string,
01121 const UndirEdge*> > UndirEdgeWriters;
01122 UndirEdgeWriters undirEdgeWriters;
01123 std::auto_ptr<IdWriterBase<UndirEdge> > undirEdgeIdWriter;
01124
01125 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
01126 EdgeWriters edgeWriters;
01127 std::auto_ptr<IdWriterBase<Edge> > edgeIdWriter;
01128
01129 };
01130
01142 template <typename _Traits = DefaultWriterTraits>
01143 class AttributeWriter : public CommonSectionWriterBase {
01144 typedef CommonSectionWriterBase Parent;
01145 typedef _Traits Traits;
01146 public:
01151 AttributeWriter(LemonWriter& _writer,
01152 const std::string& _id = std::string())
01153 : Parent(_writer), id(_id) {}
01154
01158 virtual ~AttributeWriter() {
01159 typename Writers::iterator it;
01160 for (it = writers.begin(); it != writers.end(); ++it) {
01161 delete it->second;
01162 }
01163 }
01164
01165 private:
01166 AttributeWriter(const AttributeWriter&);
01167 void operator=(AttributeWriter&);
01168
01169 public:
01173 template <typename Value>
01174 AttributeWriter& writeAttribute(const std::string& id,
01175 const Value& value) {
01176 return
01177 writeAttribute<typename Traits::template Writer<Value> >(id, value);
01178 }
01179
01183 template <typename Writer, typename Value>
01184 AttributeWriter& writeAttribute(const std::string& name,
01185 const Value& value,
01186 const Writer& writer = Writer()) {
01187 checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
01188 writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
01189 (value, writer)));
01190 return *this;
01191 }
01192
01193 protected:
01194
01198 std::string header() {
01199 return "@attributes " + id;
01200 }
01201
01205 void write(std::ostream& os) {
01206 typename Writers::iterator it;
01207 for (it = writers.begin(); it != writers.end(); ++it) {
01208 os << it->first << ' ';
01209 it->second->write(os);
01210 os << std::endl;
01211 }
01212 }
01213
01214 private:
01215 std::string id;
01216
01217 typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
01218 Writers writers;
01219 };
01220
01221
01222 }
01223 #endif