3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 ///\brief Lemon Graph Format writer.
24 #ifndef LEMON_LGF_WRITER_H
25 #define LEMON_LGF_WRITER_H
36 #include <lemon/assert.h>
37 #include <lemon/graph_utils.h>
41 namespace _writer_bits {
43 template <typename Value>
44 struct DefaultConverter {
45 std::string operator()(const Value& value) {
46 std::ostringstream os;
53 bool operator<(const T&, const T&) {
54 throw DataFormatError("Label map is not comparable");
57 template <typename _Map>
61 typedef typename Map::Key Item;
67 MapLess(const Map& map) : _map(map) {}
69 bool operator()(const Item& left, const Item& right) {
70 return _map[left] < _map[right];
74 template <typename _Item>
75 class MapStorageBase {
81 virtual ~MapStorageBase() {}
83 virtual std::string get(const Item& item) = 0;
84 virtual void sort(std::vector<Item>&) = 0;
87 template <typename _Item, typename _Map,
88 typename _Converter = DefaultConverter<typename _Map::Value> >
89 class MapStorage : public MapStorageBase<_Item> {
92 typedef _Converter Converter;
100 MapStorage(const Map& map, const Converter& converter = Converter())
101 : _map(map), _converter(converter) {}
102 virtual ~MapStorage() {}
104 virtual std::string get(const Item& item) {
105 return _converter(_map[item]);
107 virtual void sort(std::vector<Item>& items) {
108 MapLess<Map> less(_map);
109 std::sort(items.begin(), items.end(), less);
113 class ValueStorageBase {
115 ValueStorageBase() {}
116 virtual ~ValueStorageBase() {}
118 virtual std::string get() = 0;
121 template <typename _Value, typename _Converter = DefaultConverter<_Value> >
122 class ValueStorage : public ValueStorageBase {
124 typedef _Value Value;
125 typedef _Converter Converter;
129 Converter _converter;
132 ValueStorage(const Value& value, const Converter& converter = Converter())
133 : _value(value), _converter(converter) {}
135 virtual std::string get() {
136 return _converter(_value);
140 template <typename Value>
141 struct MapLookUpConverter {
142 const std::map<Value, std::string>& _map;
144 MapLookUpConverter(const std::map<Value, std::string>& map)
147 std::string operator()(const Value& str) {
148 typename std::map<Value, std::string>::const_iterator it =
150 if (it == _map.end()) {
151 throw DataFormatError("Item not found");
157 bool isWhiteSpace(char c) {
158 return c == ' ' || c == '\t' || c == '\v' ||
159 c == '\n' || c == '\r' || c == '\f';
162 bool isEscaped(char c) {
163 return c == '\\' || c == '\"' || c == '\'' ||
164 c == '\a' || c == '\b';
167 static void writeEscape(std::ostream& os, char c) {
198 std::ios::fmtflags flags = os.flags();
199 os << '\\' << std::oct << static_cast<int>(c);
208 bool requireEscape(const std::string& str) {
209 if (str.empty() || str[0] == '@') return true;
210 std::istringstream is(str);
213 if (isWhiteSpace(c) || isEscaped(c)) {
220 std::ostream& writeToken(std::ostream& os, const std::string& str) {
222 if (requireEscape(str)) {
224 for (std::string::const_iterator it = str.begin();
225 it != str.end(); ++it) {
226 writeEscape(os, *it);
237 /// \ingroup lemon_io
239 /// \brief LGF writer for directed graphs
241 /// This utility writes an \ref lgf-format "LGF" file.
243 /// The writing method does a batch processing. The user creates a
244 /// writer object, then various writing rules can be added to the
245 /// writer, and eventually the writing is executed with the \c run()
246 /// member function. A map writing rule can be added to the writer
247 /// with the \c nodeMap() or \c arcMap() members. An optional
248 /// converter parameter can also be added as a standard functor
249 /// converting from the value type of the map to std::string. If it
250 /// is set, it will determine how the map's value type is written to
251 /// the output stream. If the functor is not set, then a default
252 /// conversion will be used. The \c attribute(), \c node() and \c
253 /// arc() functions are used to add attribute writing rules.
256 /// DigraphWriter<Digraph>(std::cout, digraph).
257 /// nodeMap("coordinates", coord_map).
258 /// nodeMap("size", size).
259 /// nodeMap("title", title).
260 /// arcMap("capacity", cap_map).
261 /// node("source", src).
262 /// node("target", trg).
263 /// attribute("caption", caption).
268 /// By default, the writer does not write additional captions to the
269 /// sections, but they can be give as an optional parameter of
270 /// the \c nodes(), \c arcs() or \c
271 /// attributes() functions.
273 /// The \c skipNodes() and \c skipArcs() functions forbid the
274 /// writing of the sections. If two arc sections should be written
275 /// to the output, it can be done in two passes, the first pass
276 /// writes the node section and the first arc section, then the
277 /// second pass skips the node section and writes just the arc
278 /// section to the stream. The output stream can be retrieved with
279 /// the \c ostream() function, hence the second pass can append its
280 /// output to the output of the first pass.
281 template <typename _Digraph>
282 class DigraphWriter {
285 typedef _Digraph Digraph;
286 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
296 std::string _nodes_caption;
297 std::string _arcs_caption;
298 std::string _attributes_caption;
300 typedef std::map<Node, std::string> NodeIndex;
301 NodeIndex _node_index;
302 typedef std::map<Arc, std::string> ArcIndex;
305 typedef std::vector<std::pair<std::string,
306 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
309 typedef std::vector<std::pair<std::string,
310 _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
313 typedef std::vector<std::pair<std::string,
314 _writer_bits::ValueStorageBase*> > Attributes;
315 Attributes _attributes;
322 /// \brief Constructor
324 /// Construct a directed graph writer, which writes to the given
326 DigraphWriter(std::ostream& is, Digraph& digraph)
327 : _os(&is), local_os(false), _digraph(digraph),
328 _skip_nodes(false), _skip_arcs(false) {}
330 /// \brief Constructor
332 /// Construct a directed graph writer, which writes to the given
334 DigraphWriter(const std::string& fn, Digraph& digraph)
335 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
336 _skip_nodes(false), _skip_arcs(false) {}
338 /// \brief Constructor
340 /// Construct a directed graph writer, which writes to the given
342 DigraphWriter(const char* fn, Digraph& digraph)
343 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
344 _skip_nodes(false), _skip_arcs(false) {}
346 /// \brief Copy constructor
348 /// The copy constructor transfers all data from the other writer,
349 /// therefore the copied writer will not be usable more.
350 DigraphWriter(DigraphWriter& other)
351 : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
352 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
355 other.local_os = false;
357 _node_index.swap(other._node_index);
358 _arc_index.swap(other._arc_index);
360 _node_maps.swap(other._node_maps);
361 _arc_maps.swap(other._arc_maps);
362 _attributes.swap(other._attributes);
364 _nodes_caption = other._nodes_caption;
365 _arcs_caption = other._arcs_caption;
366 _attributes_caption = other._attributes_caption;
369 /// \brief Destructor
371 for (typename NodeMaps::iterator it = _node_maps.begin();
372 it != _node_maps.end(); ++it) {
376 for (typename ArcMaps::iterator it = _arc_maps.begin();
377 it != _arc_maps.end(); ++it) {
381 for (typename Attributes::iterator it = _attributes.begin();
382 it != _attributes.end(); ++it) {
393 DigraphWriter& operator=(const DigraphWriter&);
397 /// \name Writing rules
400 /// \brief Node map reading rule
402 /// Add a node map reading rule to the writer.
403 template <typename Map>
404 DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
405 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
406 _writer_bits::MapStorageBase<Node>* storage =
407 new _writer_bits::MapStorage<Node, Map>(map);
408 _node_maps.push_back(std::make_pair(caption, storage));
412 /// \brief Node map writing rule
414 /// Add a node map writing rule with specialized converter to the
416 template <typename Map, typename Converter>
417 DigraphWriter& nodeMap(const std::string& caption, const Map& map,
418 const Converter& converter = Converter()) {
419 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
420 _writer_bits::MapStorageBase<Node>* storage =
421 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
422 _node_maps.push_back(std::make_pair(caption, storage));
426 /// \brief Arc map writing rule
428 /// Add an arc map writing rule to the writer.
429 template <typename Map>
430 DigraphWriter& arcMap(const std::string& caption, const Map& map) {
431 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
432 _writer_bits::MapStorageBase<Arc>* storage =
433 new _writer_bits::MapStorage<Arc, Map>(map);
434 _arc_maps.push_back(std::make_pair(caption, storage));
438 /// \brief Arc map writing rule
440 /// Add an arc map writing rule with specialized converter to the
442 template <typename Map, typename Converter>
443 DigraphWriter& arcMap(const std::string& caption, const Map& map,
444 const Converter& converter = Converter()) {
445 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
446 _writer_bits::MapStorageBase<Arc>* storage =
447 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
448 _arc_maps.push_back(std::make_pair(caption, storage));
452 /// \brief Attribute writing rule
454 /// Add an attribute writing rule to the writer.
455 template <typename Value>
456 DigraphWriter& attribute(const std::string& caption, const Value& value) {
457 _writer_bits::ValueStorageBase* storage =
458 new _writer_bits::ValueStorage<Value>(value);
459 _attributes.push_back(std::make_pair(caption, storage));
463 /// \brief Attribute writing rule
465 /// Add an attribute writing rule with specialized converter to the
467 template <typename Value, typename Converter>
468 DigraphWriter& attribute(const std::string& caption, const Value& value,
469 const Converter& converter = Converter()) {
470 _writer_bits::ValueStorageBase* storage =
471 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
472 _attributes.push_back(std::make_pair(caption, storage));
476 /// \brief Node writing rule
478 /// Add a node writing rule to the writer.
479 DigraphWriter& node(const std::string& caption, const Node& node) {
480 typedef _writer_bits::MapLookUpConverter<Node> Converter;
481 Converter converter(_node_index);
482 _writer_bits::ValueStorageBase* storage =
483 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
484 _attributes.push_back(std::make_pair(caption, storage));
488 /// \brief Arc writing rule
490 /// Add an arc writing rule to writer.
491 DigraphWriter& arc(const std::string& caption, const Arc& arc) {
492 typedef _writer_bits::MapLookUpConverter<Arc> Converter;
493 Converter converter(_arc_index);
494 _writer_bits::ValueStorageBase* storage =
495 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
496 _attributes.push_back(std::make_pair(caption, storage));
500 /// \name Select section by name
503 /// \brief Set \c \@nodes section to be read
505 /// Set \c \@nodes section to be read
506 DigraphWriter& nodes(const std::string& caption) {
507 _nodes_caption = caption;
511 /// \brief Set \c \@arcs section to be read
513 /// Set \c \@arcs section to be read
514 DigraphWriter& arcs(const std::string& caption) {
515 _arcs_caption = caption;
519 /// \brief Set \c \@attributes section to be read
521 /// Set \c \@attributes section to be read
522 DigraphWriter& attributes(const std::string& caption) {
523 _attributes_caption = caption;
527 /// \name Skipping section
530 /// \brief Skip writing the node set
532 /// The \c \@nodes section will be not written to the stream.
533 DigraphWriter& skipNodes() {
534 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
538 /// \brief Skip writing arc set
540 /// The \c \@arcs section will be not written to the stream.
541 DigraphWriter& skipArcs() {
542 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
551 _writer_bits::MapStorageBase<Node>* label = 0;
552 for (typename NodeMaps::iterator it = _node_maps.begin();
553 it != _node_maps.end(); ++it) {
554 if (it->first == "label") {
561 if (!_nodes_caption.empty()) {
562 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
567 *_os << "label" << '\t';
569 for (typename NodeMaps::iterator it = _node_maps.begin();
570 it != _node_maps.end(); ++it) {
571 _writer_bits::writeToken(*_os, it->first) << '\t';
575 std::vector<Node> nodes;
576 for (NodeIt n(_digraph); n != INVALID; ++n) {
581 IdMap<Digraph, Node> id_map(_digraph);
582 _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
583 std::sort(nodes.begin(), nodes.end(), id_less);
588 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
591 std::ostringstream os;
592 os << _digraph.id(n);
593 _writer_bits::writeToken(*_os, os.str());
595 _node_index.insert(std::make_pair(n, os.str()));
597 for (typename NodeMaps::iterator it = _node_maps.begin();
598 it != _node_maps.end(); ++it) {
599 std::string value = it->second->get(n);
600 _writer_bits::writeToken(*_os, value);
601 if (it->first == "label") {
602 _node_index.insert(std::make_pair(n, value));
611 _writer_bits::MapStorageBase<Arc>* label = 0;
612 for (typename ArcMaps::iterator it = _arc_maps.begin();
613 it != _arc_maps.end(); ++it) {
614 if (it->first == "label") {
621 if (!_arcs_caption.empty()) {
622 _writer_bits::writeToken(*_os << ' ', _arcs_caption);
626 *_os << '\t' << '\t';
628 *_os << "label" << '\t';
630 for (typename ArcMaps::iterator it = _arc_maps.begin();
631 it != _arc_maps.end(); ++it) {
632 _writer_bits::writeToken(*_os, it->first) << '\t';
636 std::vector<Arc> arcs;
637 for (ArcIt n(_digraph); n != INVALID; ++n) {
642 IdMap<Digraph, Arc> id_map(_digraph);
643 _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
644 std::sort(arcs.begin(), arcs.end(), id_less);
649 for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
651 _writer_bits::writeToken(*_os, _node_index.
652 find(_digraph.source(a))->second);
654 _writer_bits::writeToken(*_os, _node_index.
655 find(_digraph.target(a))->second);
658 std::ostringstream os;
659 os << _digraph.id(a);
660 _writer_bits::writeToken(*_os, os.str());
662 _arc_index.insert(std::make_pair(a, os.str()));
664 for (typename ArcMaps::iterator it = _arc_maps.begin();
665 it != _arc_maps.end(); ++it) {
666 std::string value = it->second->get(a);
667 _writer_bits::writeToken(*_os, value);
668 if (it->first == "label") {
669 _arc_index.insert(std::make_pair(a, value));
677 void writeAttributes() {
678 if (_attributes.empty()) return;
679 *_os << "@attributes";
680 if (!_attributes_caption.empty()) {
681 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
684 for (typename Attributes::iterator it = _attributes.begin();
685 it != _attributes.end(); ++it) {
686 _writer_bits::writeToken(*_os, it->first) << ' ';
687 _writer_bits::writeToken(*_os, it->second->get());
694 /// \name Execution of the writer
697 /// \brief Start the batch processing
699 /// This function starts the batch processing
710 /// \brief Gives back the stream of the writer
712 /// Gives back the stream of the writer
713 std::ostream& ostream() {
720 /// \relates DigraphWriter
721 template <typename Digraph>
722 DigraphWriter<Digraph> digraphWriter(std::ostream& os, Digraph& digraph) {
723 DigraphWriter<Digraph> tmp(os, digraph);
727 /// \relates DigraphWriter
728 template <typename Digraph>
729 DigraphWriter<Digraph> digraphWriter(const std::string& fn,
731 DigraphWriter<Digraph> tmp(fn, digraph);
735 /// \relates DigraphWriter
736 template <typename Digraph>
737 DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
738 DigraphWriter<Digraph> tmp(fn, digraph);