* This file is a part of LEMON, a generic C++ optimization library
* Copyright (C) 2003-2008
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
///\brief Lemon Graph Format writer.
#ifndef LEMON_LGF_WRITER_H
#define LEMON_LGF_WRITER_H
#include <lemon/assert.h>
#include <lemon/graph_utils.h>
template <typename Value>
struct DefaultConverter {
std::string operator()(const Value& value) {
bool operator<(const T&, const T&) {
throw DataFormatError("Label map is not comparable");
typedef typename Map::Key Item;
MapLess(const Map& map) : _map(map) {}
bool operator()(const Item& left, const Item& right) {
return _map[left] < _map[right];
template <typename _Item>
virtual ~MapStorageBase() {}
virtual std::string get(const Item& item) = 0;
virtual void sort(std::vector<Item>&) = 0;
template <typename _Item, typename _Map,
typename _Converter = DefaultConverter<typename _Map::Value> >
class MapStorage : public MapStorageBase<_Item> {
typedef _Converter Converter;
MapStorage(const Map& map, const Converter& converter = Converter())
: _map(map), _converter(converter) {}
virtual std::string get(const Item& item) {
return _converter(_map[item]);
virtual void sort(std::vector<Item>& items) {
std::sort(items.begin(), items.end(), less);
virtual ~ValueStorageBase() {}
virtual std::string get() = 0;
template <typename _Value, typename _Converter = DefaultConverter<_Value> >
class ValueStorage : public ValueStorageBase {
typedef _Converter Converter;
ValueStorage(const Value& value, const Converter& converter = Converter())
: _value(value), _converter(converter) {}
virtual std::string get() {
return _converter(_value);
template <typename Value>
struct MapLookUpConverter {
const std::map<Value, std::string>& _map;
MapLookUpConverter(const std::map<Value, std::string>& map)
std::string operator()(const Value& str) {
typename std::map<Value, std::string>::const_iterator it =
throw DataFormatError("Item not found");
bool isWhiteSpace(char c) {
return c == ' ' || c == '\t' || c == '\v' ||
c == '\n' || c == '\r' || c == '\f';
return c == '\\' || c == '\"' || c == '\'' ||
static void writeEscape(std::ostream& os, char c) {
os << '\\' << std::oct << static_cast<int>(c);
bool requireEscape(const std::string& str) {
std::istringstream is(str);
if (isWhiteSpace(c) || isEscaped(c)) {
std::ostream& writeToken(std::ostream& os, const std::string& str) {
if (requireEscape(str)) {
for (std::string::const_iterator it = str.begin();
template <typename _Digraph>
typedef _Digraph Digraph;
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
std::string _nodes_caption;
std::string _arcs_caption;
std::string _attributes_caption;
typedef std::map<Node, std::string> NodeIndex;
typedef std::map<Arc, std::string> ArcIndex;
typedef std::vector<std::pair<std::string,
_writer_bits::MapStorageBase<Node>* > > NodeMaps;
typedef std::vector<std::pair<std::string,
_writer_bits::MapStorageBase<Arc>* > >ArcMaps;
typedef std::vector<std::pair<std::string,
_writer_bits::ValueStorageBase*> > Attributes;
DigraphWriter(std::ostream& is, Digraph& digraph)
: _os(&is), local_os(false), _digraph(digraph),
_skip_nodes(false), _skip_arcs(false) {}
DigraphWriter(const std::string& fn, Digraph& digraph)
: _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
_skip_nodes(false), _skip_arcs(false) {}
DigraphWriter(const char* fn, Digraph& digraph)
: _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
_skip_nodes(false), _skip_arcs(false) {}
DigraphWriter(DigraphWriter& other)
: _os(other._os), local_os(other.local_os), _digraph(other._digraph),
_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
_node_index.swap(other._node_index);
_arc_index.swap(other._arc_index);
_node_maps.swap(other._node_maps);
_arc_maps.swap(other._arc_maps);
_attributes.swap(other._attributes);
_nodes_caption = other._nodes_caption;
_arcs_caption = other._arcs_caption;
_attributes_caption = other._attributes_caption;
for (typename NodeMaps::iterator it = _node_maps.begin();
it != _node_maps.end(); ++it) {
for (typename ArcMaps::iterator it = _arc_maps.begin();
it != _arc_maps.end(); ++it) {
for (typename Attributes::iterator it = _attributes.begin();
it != _attributes.end(); ++it) {
DigraphWriter& operator=(const DigraphWriter&);
DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
_writer_bits::MapStorageBase<Node>* storage =
new _writer_bits::MapStorage<Node, Map>(map);
_node_maps.push_back(std::make_pair(caption, storage));
template <typename Map, typename Converter>
DigraphWriter& nodeMap(const std::string& caption, const Map& map,
const Converter& converter = Converter()) {
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
_writer_bits::MapStorageBase<Node>* storage =
new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
_node_maps.push_back(std::make_pair(caption, storage));
DigraphWriter& arcMap(const std::string& caption, const Map& map) {
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
_writer_bits::MapStorageBase<Arc>* storage =
new _writer_bits::MapStorage<Arc, Map>(map);
_arc_maps.push_back(std::make_pair(caption, storage));
template <typename Map, typename Converter>
DigraphWriter& arcMap(const std::string& caption, const Map& map,
const Converter& converter = Converter()) {
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
_writer_bits::MapStorageBase<Arc>* storage =
new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
_arc_maps.push_back(std::make_pair(caption, storage));
template <typename Value>
DigraphWriter& attribute(const std::string& caption, const Value& value) {
_writer_bits::ValueStorageBase* storage =
new _writer_bits::ValueStorage<Value>(value);
_attributes.push_back(std::make_pair(caption, storage));
template <typename Value, typename Converter>
DigraphWriter& attribute(const std::string& caption, const Value& value,
const Converter& converter = Converter()) {
_writer_bits::ValueStorageBase* storage =
new _writer_bits::ValueStorage<Value, Converter>(value, converter);
_attributes.push_back(std::make_pair(caption, storage));
DigraphWriter& node(const std::string& caption, const Node& node) {
typedef _writer_bits::MapLookUpConverter<Node> Converter;
Converter converter(_node_index);
_writer_bits::ValueStorageBase* storage =
new _writer_bits::ValueStorage<Node, Converter>(node, converter);
_attributes.push_back(std::make_pair(caption, storage));
DigraphWriter& arc(const std::string& caption, const Arc& arc) {
typedef _writer_bits::MapLookUpConverter<Arc> Converter;
Converter converter(_arc_index);
_writer_bits::ValueStorageBase* storage =
new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
_attributes.push_back(std::make_pair(caption, storage));
DigraphWriter& nodes(const std::string& caption) {
_nodes_caption = caption;
DigraphWriter& arcs(const std::string& caption) {
DigraphWriter& attributes(const std::string& caption) {
_attributes_caption = caption;
DigraphWriter& skipNodes() {
LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
DigraphWriter& skipArcs() {
LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
_writer_bits::MapStorageBase<Node>* label = 0;
for (typename NodeMaps::iterator it = _node_maps.begin();
it != _node_maps.end(); ++it) {
if (it->first == "label") {
if (!_nodes_caption.empty()) {
*_os << ' ' << _nodes_caption;
for (typename NodeMaps::iterator it = _node_maps.begin();
it != _node_maps.end(); ++it) {
*_os << it->first << '\t';
for (NodeIt n(_digraph); n != INVALID; ++n) {
IdMap<Digraph, Node> id_map(_digraph);
_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
std::sort(nodes.begin(), nodes.end(), id_less);
for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
_writer_bits::writeToken(*_os, os.str());
_node_index.insert(std::make_pair(n, os.str()));
for (typename NodeMaps::iterator it = _node_maps.begin();
it != _node_maps.end(); ++it) {
std::string value = it->second->get(n);
_writer_bits::writeToken(*_os, value);
if (it->first == "label") {
_node_index.insert(std::make_pair(n, value));
_writer_bits::MapStorageBase<Arc>* label = 0;
for (typename ArcMaps::iterator it = _arc_maps.begin();
it != _arc_maps.end(); ++it) {
if (it->first == "label") {
if (!_arcs_caption.empty()) {
*_os << ' ' << _arcs_caption;
for (typename ArcMaps::iterator it = _arc_maps.begin();
it != _arc_maps.end(); ++it) {
*_os << it->first << '\t';
for (ArcIt n(_digraph); n != INVALID; ++n) {
IdMap<Digraph, Arc> id_map(_digraph);
_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
std::sort(arcs.begin(), arcs.end(), id_less);
for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
_writer_bits::writeToken(*_os, _node_index.
find(_digraph.source(a))->second);
_writer_bits::writeToken(*_os, _node_index.
find(_digraph.target(a))->second);
_writer_bits::writeToken(*_os, os.str());
_arc_index.insert(std::make_pair(a, os.str()));
for (typename ArcMaps::iterator it = _arc_maps.begin();
it != _arc_maps.end(); ++it) {
std::string value = it->second->get(a);
_writer_bits::writeToken(*_os, value);
if (it->first == "label") {
_arc_index.insert(std::make_pair(a, value));
if (_attributes.empty()) return;
if (!_attributes_caption.empty()) {
*_os << ' ' << _attributes_caption;
for (typename Attributes::iterator it = _attributes.begin();
it != _attributes.end(); ++it) {
*_os << it->first << ' ';
_writer_bits::writeToken(*_os, it->second->get());
template <typename Digraph>
DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) {
return DigraphWriter<Digraph>(is, digraph);
template <typename Digraph>
DigraphWriter<Digraph> digraphWriter(const std::string& fn,
return DigraphWriter<Digraph>(fn, digraph);
template <typename Digraph>
DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
return DigraphWriter<Digraph>(fn, digraph);