lemon/lgf_writer.h
changeset 176 47b69d4b0759
parent 163 c82fd9568d75
child 185 33e45a9b868c
equal deleted inserted replaced
5:3f179fd8d2bc 6:ed00337fdec4
    69       bool operator()(const Item& left, const Item& right) {
    69       bool operator()(const Item& left, const Item& right) {
    70 	return _map[left] < _map[right];
    70 	return _map[left] < _map[right];
    71       }
    71       }
    72     };
    72     };
    73 
    73 
       
    74     template <typename _Graph, bool _dir, typename _Map>
       
    75     class GraphArcMapLess {
       
    76     public:
       
    77       typedef _Map Map;
       
    78       typedef _Graph Graph;
       
    79       typedef typename Graph::Edge Item;
       
    80 
       
    81     private:
       
    82       const Graph& _graph;
       
    83       const Map& _map;
       
    84       
       
    85     public:
       
    86       GraphArcMapLess(const Graph& graph, const Map& map) 
       
    87 	: _graph(graph), _map(map) {}
       
    88 
       
    89       bool operator()(const Item& left, const Item& right) {
       
    90 	return _map[_graph.direct(left, _dir)] < 
       
    91 	  _map[_graph.direct(right, _dir)];
       
    92       }
       
    93     };
       
    94 
    74     template <typename _Item>    
    95     template <typename _Item>    
    75     class MapStorageBase {
    96     class MapStorageBase {
    76     public:
    97     public:
    77       typedef _Item Item;
    98       typedef _Item Item;
    78 
    99 
   104       virtual std::string get(const Item& item) {
   125       virtual std::string get(const Item& item) {
   105 	return _converter(_map[item]);
   126 	return _converter(_map[item]);
   106       }
   127       }
   107       virtual void sort(std::vector<Item>& items) {
   128       virtual void sort(std::vector<Item>& items) {
   108 	MapLess<Map> less(_map);
   129 	MapLess<Map> less(_map);
       
   130 	std::sort(items.begin(), items.end(), less);
       
   131       }
       
   132     };
       
   133 
       
   134     template <typename _Graph, bool _dir, typename _Map, 
       
   135 	      typename _Converter = DefaultConverter<typename _Map::Value> >
       
   136     class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
       
   137     public:
       
   138       typedef _Map Map;
       
   139       typedef _Converter Converter;
       
   140       typedef _Graph Graph;
       
   141       typedef typename Graph::Edge Item;
       
   142       static const bool dir = _dir;
       
   143       
       
   144     private:
       
   145       const Graph& _graph;
       
   146       const Map& _map;
       
   147       Converter _converter;
       
   148 
       
   149     public:
       
   150       GraphArcMapStorage(const Graph& graph, const Map& map,  
       
   151 			 const Converter& converter = Converter()) 
       
   152 	: _graph(graph), _map(map), _converter(converter) {}
       
   153       virtual ~GraphArcMapStorage() {}
       
   154 
       
   155       virtual std::string get(const Item& item) {
       
   156 	return _converter(_map[_graph.direct(item, dir)]);
       
   157       }
       
   158       virtual void sort(std::vector<Item>& items) {
       
   159 	GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
   109 	std::sort(items.begin(), items.end(), less);
   160 	std::sort(items.begin(), items.end(), less);
   110       }
   161       }
   111     };
   162     };
   112 
   163 
   113     class ValueStorageBase {
   164     class ValueStorageBase {
   149 	  _map.find(str);
   200 	  _map.find(str);
   150 	if (it == _map.end()) {
   201 	if (it == _map.end()) {
   151 	  throw DataFormatError("Item not found");
   202 	  throw DataFormatError("Item not found");
   152 	}
   203 	}
   153 	return it->second;
   204 	return it->second;
       
   205       }
       
   206     };
       
   207 
       
   208     template <typename Graph>
       
   209     struct GraphArcLookUpConverter {
       
   210       const Graph& _graph;
       
   211       const std::map<typename Graph::Edge, std::string>& _map;
       
   212       
       
   213       GraphArcLookUpConverter(const Graph& graph, 
       
   214 			      const std::map<typename Graph::Edge, 
       
   215 			                     std::string>& map) 
       
   216 	: _graph(graph), _map(map) {}
       
   217       
       
   218       std::string operator()(const typename Graph::Arc& val) {
       
   219 	typename std::map<typename Graph::Edge, std::string>
       
   220 	  ::const_iterator it = _map.find(val);
       
   221 	if (it == _map.end()) {
       
   222 	  throw DataFormatError("Item not found");
       
   223 	}
       
   224 	return (_graph.direction(val) ? '+' : '-') + it->second;
   154       }
   225       }
   155     };
   226     };
   156 
   227 
   157     bool isWhiteSpace(char c) {
   228     bool isWhiteSpace(char c) {
   158       return c == ' ' || c == '\t' || c == '\v' || 
   229       return c == ' ' || c == '\t' || c == '\v' || 
   736   template <typename Digraph>
   807   template <typename Digraph>
   737   DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
   808   DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
   738     DigraphWriter<Digraph> tmp(fn, digraph);
   809     DigraphWriter<Digraph> tmp(fn, digraph);
   739     return tmp;
   810     return tmp;
   740   }
   811   }
       
   812 
       
   813   /// \ingroup lemon_io
       
   814   ///  
       
   815   /// \brief LGF writer for directed graphs
       
   816   ///
       
   817   /// This utility writes an \ref lgf-format "LGF" file.
       
   818   template <typename _Graph>
       
   819   class GraphWriter {
       
   820   public:
       
   821 
       
   822     typedef _Graph Graph;
       
   823     TEMPLATE_GRAPH_TYPEDEFS(Graph);
       
   824     
       
   825   private:
       
   826 
       
   827 
       
   828     std::ostream* _os;
       
   829     bool local_os;
       
   830 
       
   831     Graph& _graph;
       
   832 
       
   833     std::string _nodes_caption;
       
   834     std::string _edges_caption;
       
   835     std::string _attributes_caption;
       
   836     
       
   837     typedef std::map<Node, std::string> NodeIndex;
       
   838     NodeIndex _node_index;
       
   839     typedef std::map<Edge, std::string> EdgeIndex;
       
   840     EdgeIndex _edge_index;
       
   841 
       
   842     typedef std::vector<std::pair<std::string, 
       
   843       _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
       
   844     NodeMaps _node_maps; 
       
   845 
       
   846     typedef std::vector<std::pair<std::string, 
       
   847       _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
       
   848     EdgeMaps _edge_maps;
       
   849 
       
   850     typedef std::vector<std::pair<std::string, 
       
   851       _writer_bits::ValueStorageBase*> > Attributes;
       
   852     Attributes _attributes;
       
   853 
       
   854     bool _skip_nodes;
       
   855     bool _skip_edges;
       
   856 
       
   857   public:
       
   858 
       
   859     /// \brief Constructor
       
   860     ///
       
   861     /// Construct a directed graph writer, which writes to the given
       
   862     /// output stream.
       
   863     GraphWriter(std::ostream& is, Graph& graph) 
       
   864       : _os(&is), local_os(false), _graph(graph),
       
   865 	_skip_nodes(false), _skip_edges(false) {}
       
   866 
       
   867     /// \brief Constructor
       
   868     ///
       
   869     /// Construct a directed graph writer, which writes to the given
       
   870     /// output file.
       
   871     GraphWriter(const std::string& fn, Graph& graph) 
       
   872       : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
       
   873 	_skip_nodes(false), _skip_edges(false) {}
       
   874 
       
   875     /// \brief Constructor
       
   876     ///
       
   877     /// Construct a directed graph writer, which writes to the given
       
   878     /// output file.
       
   879     GraphWriter(const char* fn, Graph& graph) 
       
   880       : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
       
   881 	_skip_nodes(false), _skip_edges(false) {}
       
   882 
       
   883     /// \brief Copy constructor
       
   884     ///
       
   885     /// The copy constructor transfers all data from the other writer,
       
   886     /// therefore the copied writer will not be usable more. 
       
   887     GraphWriter(GraphWriter& other) 
       
   888       : _os(other._os), local_os(other.local_os), _graph(other._graph),
       
   889 	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
       
   890 
       
   891       other._os = 0;
       
   892       other.local_os = false;
       
   893 
       
   894       _node_index.swap(other._node_index);
       
   895       _edge_index.swap(other._edge_index);
       
   896 
       
   897       _node_maps.swap(other._node_maps);
       
   898       _edge_maps.swap(other._edge_maps);
       
   899       _attributes.swap(other._attributes);
       
   900 
       
   901       _nodes_caption = other._nodes_caption;
       
   902       _edges_caption = other._edges_caption;
       
   903       _attributes_caption = other._attributes_caption;
       
   904     }
       
   905 
       
   906     /// \brief Destructor
       
   907     ~GraphWriter() {
       
   908       for (typename NodeMaps::iterator it = _node_maps.begin(); 
       
   909 	   it != _node_maps.end(); ++it) {
       
   910 	delete it->second;
       
   911       }
       
   912 
       
   913       for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
       
   914 	   it != _edge_maps.end(); ++it) {
       
   915 	delete it->second;
       
   916       }
       
   917 
       
   918       for (typename Attributes::iterator it = _attributes.begin(); 
       
   919 	   it != _attributes.end(); ++it) {
       
   920 	delete it->second;
       
   921       }
       
   922 
       
   923       if (local_os) {
       
   924 	delete _os;
       
   925       }
       
   926     }
       
   927 
       
   928   private:
       
   929     
       
   930     GraphWriter& operator=(const GraphWriter&);
       
   931 
       
   932   public:
       
   933 
       
   934     /// \name Writing rules
       
   935     /// @{
       
   936     
       
   937     /// \brief Node map reading rule
       
   938     ///
       
   939     /// Add a node map reading rule to the writer.
       
   940     template <typename Map>
       
   941     GraphWriter& nodeMap(const std::string& caption, const Map& map) {
       
   942       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
   943       _writer_bits::MapStorageBase<Node>* storage = 
       
   944 	new _writer_bits::MapStorage<Node, Map>(map);
       
   945       _node_maps.push_back(std::make_pair(caption, storage));
       
   946       return *this;
       
   947     }
       
   948 
       
   949     /// \brief Node map writing rule
       
   950     ///
       
   951     /// Add a node map writing rule with specialized converter to the
       
   952     /// writer.
       
   953     template <typename Map, typename Converter>
       
   954     GraphWriter& nodeMap(const std::string& caption, const Map& map, 
       
   955 			   const Converter& converter = Converter()) {
       
   956       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
   957       _writer_bits::MapStorageBase<Node>* storage = 
       
   958 	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
       
   959       _node_maps.push_back(std::make_pair(caption, storage));
       
   960       return *this;
       
   961     }
       
   962 
       
   963     /// \brief Edge map writing rule
       
   964     ///
       
   965     /// Add an edge map writing rule to the writer.
       
   966     template <typename Map>
       
   967     GraphWriter& edgeMap(const std::string& caption, const Map& map) {
       
   968       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
       
   969       _writer_bits::MapStorageBase<Edge>* storage = 
       
   970 	new _writer_bits::MapStorage<Edge, Map>(map);
       
   971       _edge_maps.push_back(std::make_pair(caption, storage));
       
   972       return *this;
       
   973     }
       
   974 
       
   975     /// \brief Edge map writing rule
       
   976     ///
       
   977     /// Add an edge map writing rule with specialized converter to the
       
   978     /// writer.
       
   979     template <typename Map, typename Converter>
       
   980     GraphWriter& edgeMap(const std::string& caption, const Map& map, 
       
   981 			  const Converter& converter = Converter()) {
       
   982       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
       
   983       _writer_bits::MapStorageBase<Edge>* storage = 
       
   984 	new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
       
   985       _edge_maps.push_back(std::make_pair(caption, storage));
       
   986       return *this;
       
   987     }
       
   988 
       
   989     /// \brief Arc map writing rule
       
   990     ///
       
   991     /// Add an arc map writing rule to the writer.
       
   992     template <typename Map>
       
   993     GraphWriter& arcMap(const std::string& caption, const Map& map) {
       
   994       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
       
   995       _writer_bits::MapStorageBase<Edge>* forward_storage = 
       
   996 	new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
       
   997       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
       
   998       _writer_bits::MapStorageBase<Edge>* backward_storage = 
       
   999 	new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
       
  1000       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
       
  1001       return *this;
       
  1002     }
       
  1003 
       
  1004     /// \brief Arc map writing rule
       
  1005     ///
       
  1006     /// Add an arc map writing rule with specialized converter to the
       
  1007     /// writer.
       
  1008     template <typename Map, typename Converter>
       
  1009     GraphWriter& arcMap(const std::string& caption, const Map& map, 
       
  1010 			  const Converter& converter = Converter()) {
       
  1011       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
       
  1012       _writer_bits::MapStorageBase<Edge>* forward_storage = 
       
  1013 	new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
       
  1014 	(_graph, map, converter);
       
  1015       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
       
  1016       _writer_bits::MapStorageBase<Edge>* backward_storage = 
       
  1017 	new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
       
  1018 	(_graph, map, converter);
       
  1019       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
       
  1020       return *this;
       
  1021     }
       
  1022 
       
  1023     /// \brief Attribute writing rule
       
  1024     ///
       
  1025     /// Add an attribute writing rule to the writer.
       
  1026     template <typename Value>
       
  1027     GraphWriter& attribute(const std::string& caption, const Value& value) {
       
  1028       _writer_bits::ValueStorageBase* storage = 
       
  1029 	new _writer_bits::ValueStorage<Value>(value);
       
  1030       _attributes.push_back(std::make_pair(caption, storage));
       
  1031       return *this;
       
  1032     }
       
  1033 
       
  1034     /// \brief Attribute writing rule
       
  1035     ///
       
  1036     /// Add an attribute writing rule with specialized converter to the
       
  1037     /// writer.
       
  1038     template <typename Value, typename Converter>
       
  1039     GraphWriter& attribute(const std::string& caption, const Value& value, 
       
  1040 			     const Converter& converter = Converter()) {
       
  1041       _writer_bits::ValueStorageBase* storage = 
       
  1042 	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
       
  1043       _attributes.push_back(std::make_pair(caption, storage));
       
  1044       return *this;
       
  1045     }
       
  1046 
       
  1047     /// \brief Node writing rule
       
  1048     ///
       
  1049     /// Add a node writing rule to the writer.
       
  1050     GraphWriter& node(const std::string& caption, const Node& node) {
       
  1051       typedef _writer_bits::MapLookUpConverter<Node> Converter;
       
  1052       Converter converter(_node_index);
       
  1053       _writer_bits::ValueStorageBase* storage = 
       
  1054 	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
       
  1055       _attributes.push_back(std::make_pair(caption, storage));
       
  1056       return *this;
       
  1057     }
       
  1058 
       
  1059     /// \brief Edge writing rule
       
  1060     ///
       
  1061     /// Add an edge writing rule to writer.
       
  1062     GraphWriter& edge(const std::string& caption, const Edge& edge) {
       
  1063       typedef _writer_bits::MapLookUpConverter<Edge> Converter;
       
  1064       Converter converter(_edge_index);
       
  1065       _writer_bits::ValueStorageBase* storage = 
       
  1066 	new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
       
  1067       _attributes.push_back(std::make_pair(caption, storage));
       
  1068       return *this;
       
  1069     }
       
  1070 
       
  1071     /// \brief Arc writing rule
       
  1072     ///
       
  1073     /// Add an arc writing rule to writer.
       
  1074     GraphWriter& arc(const std::string& caption, const Arc& arc) {
       
  1075       typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
       
  1076       Converter converter(_graph, _edge_index);
       
  1077       _writer_bits::ValueStorageBase* storage = 
       
  1078 	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
       
  1079       _attributes.push_back(std::make_pair(caption, storage));
       
  1080       return *this;
       
  1081     }
       
  1082 
       
  1083     /// \name Select section by name
       
  1084     /// @{
       
  1085 
       
  1086     /// \brief Set \c \@nodes section to be read
       
  1087     ///
       
  1088     /// Set \c \@nodes section to be read
       
  1089     GraphWriter& nodes(const std::string& caption) {
       
  1090       _nodes_caption = caption;
       
  1091       return *this;
       
  1092     }
       
  1093 
       
  1094     /// \brief Set \c \@edges section to be read
       
  1095     ///
       
  1096     /// Set \c \@edges section to be read
       
  1097     GraphWriter& edges(const std::string& caption) {
       
  1098       _edges_caption = caption;
       
  1099       return *this;
       
  1100     }
       
  1101 
       
  1102     /// \brief Set \c \@attributes section to be read
       
  1103     ///
       
  1104     /// Set \c \@attributes section to be read
       
  1105     GraphWriter& attributes(const std::string& caption) {
       
  1106       _attributes_caption = caption;
       
  1107       return *this;
       
  1108     }
       
  1109 
       
  1110     /// \name Skipping section
       
  1111     /// @{
       
  1112 
       
  1113     /// \brief Skip writing the node set
       
  1114     ///
       
  1115     /// The \c \@nodes section will be not written to the stream.
       
  1116     GraphWriter& skipNodes() {
       
  1117       LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
       
  1118       return *this;
       
  1119     }
       
  1120 
       
  1121     /// \brief Skip writing edge set
       
  1122     ///
       
  1123     /// The \c \@edges section will be not written to the stream.
       
  1124     GraphWriter& skipEdges() {
       
  1125       LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
       
  1126       return *this;
       
  1127     }
       
  1128 
       
  1129     /// @}
       
  1130 
       
  1131   private:
       
  1132 
       
  1133     void writeNodes() {
       
  1134       _writer_bits::MapStorageBase<Node>* label = 0;
       
  1135       for (typename NodeMaps::iterator it = _node_maps.begin();
       
  1136 	   it != _node_maps.end(); ++it) {
       
  1137         if (it->first == "label") {
       
  1138 	  label = it->second;
       
  1139 	  break;
       
  1140 	}
       
  1141       }
       
  1142 
       
  1143       *_os << "@nodes";
       
  1144       if (!_nodes_caption.empty()) {
       
  1145 	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
       
  1146       }
       
  1147       *_os << std::endl;
       
  1148 
       
  1149       if (label == 0) {
       
  1150 	*_os << "label" << '\t';
       
  1151       }
       
  1152       for (typename NodeMaps::iterator it = _node_maps.begin();
       
  1153 	   it != _node_maps.end(); ++it) {
       
  1154 	_writer_bits::writeToken(*_os, it->first) << '\t';
       
  1155       }
       
  1156       *_os << std::endl;
       
  1157 
       
  1158       std::vector<Node> nodes;
       
  1159       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1160 	nodes.push_back(n);
       
  1161       }
       
  1162       
       
  1163       if (label == 0) {
       
  1164 	IdMap<Graph, Node> id_map(_graph);
       
  1165 	_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
       
  1166 	std::sort(nodes.begin(), nodes.end(), id_less);
       
  1167       } else {
       
  1168 	label->sort(nodes);
       
  1169       }
       
  1170 
       
  1171       for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
       
  1172 	Node n = nodes[i];
       
  1173 	if (label == 0) {
       
  1174 	  std::ostringstream os;
       
  1175 	  os << _graph.id(n);
       
  1176 	  _writer_bits::writeToken(*_os, os.str());
       
  1177 	  *_os << '\t';
       
  1178 	  _node_index.insert(std::make_pair(n, os.str()));
       
  1179 	}
       
  1180 	for (typename NodeMaps::iterator it = _node_maps.begin();
       
  1181 	     it != _node_maps.end(); ++it) {
       
  1182 	  std::string value = it->second->get(n);
       
  1183 	  _writer_bits::writeToken(*_os, value);
       
  1184 	  if (it->first == "label") {
       
  1185 	    _node_index.insert(std::make_pair(n, value));
       
  1186 	  }
       
  1187 	  *_os << '\t';
       
  1188 	}
       
  1189 	*_os << std::endl;
       
  1190       }
       
  1191     }
       
  1192 
       
  1193     void writeEdges() {
       
  1194       _writer_bits::MapStorageBase<Edge>* label = 0;
       
  1195       for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  1196 	   it != _edge_maps.end(); ++it) {
       
  1197         if (it->first == "label") {
       
  1198 	  label = it->second;
       
  1199 	  break;
       
  1200 	}
       
  1201       }
       
  1202 
       
  1203       *_os << "@edges";
       
  1204       if (!_edges_caption.empty()) {
       
  1205 	_writer_bits::writeToken(*_os << ' ', _edges_caption);
       
  1206       }
       
  1207       *_os << std::endl;
       
  1208 
       
  1209       *_os << '\t' << '\t';
       
  1210       if (label == 0) {
       
  1211 	*_os << "label" << '\t';
       
  1212       }
       
  1213       for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  1214 	   it != _edge_maps.end(); ++it) {
       
  1215 	_writer_bits::writeToken(*_os, it->first) << '\t';
       
  1216       }
       
  1217       *_os << std::endl;
       
  1218 
       
  1219       std::vector<Edge> edges;
       
  1220       for (EdgeIt n(_graph); n != INVALID; ++n) {
       
  1221 	edges.push_back(n);
       
  1222       }
       
  1223       
       
  1224       if (label == 0) {
       
  1225 	IdMap<Graph, Edge> id_map(_graph);
       
  1226 	_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
       
  1227 	std::sort(edges.begin(), edges.end(), id_less);
       
  1228       } else {
       
  1229 	label->sort(edges);
       
  1230       }
       
  1231 
       
  1232       for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
       
  1233 	Edge e = edges[i];
       
  1234 	_writer_bits::writeToken(*_os, _node_index.
       
  1235 				 find(_graph.u(e))->second);
       
  1236 	*_os << '\t';
       
  1237 	_writer_bits::writeToken(*_os, _node_index.
       
  1238 				 find(_graph.v(e))->second);
       
  1239 	*_os << '\t';
       
  1240 	if (label == 0) {
       
  1241 	  std::ostringstream os;
       
  1242 	  os << _graph.id(e);
       
  1243 	  _writer_bits::writeToken(*_os, os.str());
       
  1244 	  *_os << '\t';
       
  1245 	  _edge_index.insert(std::make_pair(e, os.str()));
       
  1246 	}
       
  1247 	for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  1248 	     it != _edge_maps.end(); ++it) {
       
  1249 	  std::string value = it->second->get(e);
       
  1250 	  _writer_bits::writeToken(*_os, value);
       
  1251 	  if (it->first == "label") {
       
  1252 	    _edge_index.insert(std::make_pair(e, value));
       
  1253 	  }
       
  1254 	  *_os << '\t';
       
  1255 	}
       
  1256 	*_os << std::endl;
       
  1257       }
       
  1258     }
       
  1259 
       
  1260     void writeAttributes() {
       
  1261       if (_attributes.empty()) return;
       
  1262       *_os << "@attributes";
       
  1263       if (!_attributes_caption.empty()) {
       
  1264 	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
       
  1265       }
       
  1266       *_os << std::endl;
       
  1267       for (typename Attributes::iterator it = _attributes.begin();
       
  1268 	   it != _attributes.end(); ++it) {
       
  1269 	_writer_bits::writeToken(*_os, it->first) << ' ';
       
  1270 	_writer_bits::writeToken(*_os, it->second->get());
       
  1271 	*_os << std::endl;
       
  1272       }
       
  1273     }
       
  1274     
       
  1275   public:
       
  1276     
       
  1277     /// \name Execution of the writer    
       
  1278     /// @{
       
  1279 
       
  1280     /// \brief Start the batch processing
       
  1281     ///
       
  1282     /// This function starts the batch processing
       
  1283     void run() {
       
  1284       if (!_skip_nodes) {
       
  1285 	writeNodes();
       
  1286       }
       
  1287       if (!_skip_edges) {      
       
  1288 	writeEdges();
       
  1289       }
       
  1290       writeAttributes();
       
  1291     }
       
  1292 
       
  1293     /// \brief Gives back the stream of the writer
       
  1294     ///
       
  1295     /// Gives back the stream of the writer
       
  1296     std::ostream& ostream() {
       
  1297       return *_os;
       
  1298     }
       
  1299 
       
  1300     /// @}
       
  1301   };
       
  1302 
       
  1303   /// \relates GraphWriter
       
  1304   template <typename Graph>
       
  1305   GraphWriter<Graph> graphWriter(std::ostream& os, Graph& graph) {
       
  1306     GraphWriter<Graph> tmp(os, graph);
       
  1307     return tmp;
       
  1308   }
       
  1309 
       
  1310   /// \relates GraphWriter
       
  1311   template <typename Graph>
       
  1312   GraphWriter<Graph> graphWriter(const std::string& fn, Graph& graph) {
       
  1313     GraphWriter<Graph> tmp(fn, graph);
       
  1314     return tmp;
       
  1315   }
       
  1316 
       
  1317   /// \relates GraphWriter
       
  1318   template <typename Graph>
       
  1319   GraphWriter<Graph> graphWriter(const char* fn, Graph& graph) {
       
  1320     GraphWriter<Graph> tmp(fn, graph);
       
  1321     return tmp;
       
  1322   }
   741 }
  1323 }
   742 
  1324 
   743 #endif
  1325 #endif