1.1 --- a/lemon/lgf_reader.h Sat May 31 12:34:44 2008 +0200
1.2 +++ b/lemon/lgf_reader.h Sat May 31 12:49:18 2008 +0200
1.3 @@ -100,6 +100,32 @@
1.4 }
1.5 };
1.6
1.7 + template <typename _Graph, bool _dir, typename _Map,
1.8 + typename _Converter = DefaultConverter<typename _Map::Value> >
1.9 + class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
1.10 + public:
1.11 + typedef _Map Map;
1.12 + typedef _Converter Converter;
1.13 + typedef _Graph Graph;
1.14 + typedef typename Graph::Edge Item;
1.15 + static const bool dir = _dir;
1.16 +
1.17 + private:
1.18 + const Graph& _graph;
1.19 + Map& _map;
1.20 + Converter _converter;
1.21 +
1.22 + public:
1.23 + GraphArcMapStorage(const Graph& graph, Map& map,
1.24 + const Converter& converter = Converter())
1.25 + : _graph(graph), _map(map), _converter(converter) {}
1.26 + virtual ~GraphArcMapStorage() {}
1.27 +
1.28 + virtual void set(const Item& item ,const std::string& value) {
1.29 + _map.set(_graph.direct(item, dir), _converter(value));
1.30 + }
1.31 + };
1.32 +
1.33 class ValueStorageBase {
1.34 public:
1.35 ValueStorageBase() {}
1.36 @@ -146,6 +172,29 @@
1.37 }
1.38 };
1.39
1.40 + template <typename Graph>
1.41 + struct GraphArcLookUpConverter {
1.42 + const Graph& _graph;
1.43 + const std::map<std::string, typename Graph::Edge>& _map;
1.44 +
1.45 + GraphArcLookUpConverter(const Graph& graph,
1.46 + const std::map<std::string,
1.47 + typename Graph::Edge>& map)
1.48 + : _graph(graph), _map(map) {}
1.49 +
1.50 + typename Graph::Arc operator()(const std::string& str) {
1.51 + if (str.empty() || (str[0] != '+' && str[0] != '-')) {
1.52 + throw DataFormatError("Item must start with '+' or '-'");
1.53 + }
1.54 + typename std::map<std::string, typename Graph::Edge>
1.55 + ::const_iterator it = _map.find(str.substr(1));
1.56 + if (it == _map.end()) {
1.57 + throw DataFormatError("Item not found");
1.58 + }
1.59 + return _graph.direct(it->second, str[0] == '+');
1.60 + }
1.61 + };
1.62 +
1.63 bool isWhiteSpace(char c) {
1.64 return c == ' ' || c == '\t' || c == '\v' ||
1.65 c == '\n' || c == '\r' || c == '\f';
1.66 @@ -1180,6 +1229,848 @@
1.67 DigraphReader<Digraph> tmp(fn, digraph);
1.68 return tmp;
1.69 }
1.70 +
1.71 + /// \ingroup lemon_io
1.72 + ///
1.73 + /// \brief LGF reader for undirected graphs
1.74 + ///
1.75 + /// This utility reads an \ref lgf-format "LGF" file.
1.76 + template <typename _Graph>
1.77 + class GraphReader {
1.78 + public:
1.79 +
1.80 + typedef _Graph Graph;
1.81 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
1.82 +
1.83 + private:
1.84 +
1.85 +
1.86 + std::istream* _is;
1.87 + bool local_is;
1.88 +
1.89 + Graph& _graph;
1.90 +
1.91 + std::string _nodes_caption;
1.92 + std::string _edges_caption;
1.93 + std::string _attributes_caption;
1.94 +
1.95 + typedef std::map<std::string, Node> NodeIndex;
1.96 + NodeIndex _node_index;
1.97 + typedef std::map<std::string, Edge> EdgeIndex;
1.98 + EdgeIndex _edge_index;
1.99 +
1.100 + typedef std::vector<std::pair<std::string,
1.101 + _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1.102 + NodeMaps _node_maps;
1.103 +
1.104 + typedef std::vector<std::pair<std::string,
1.105 + _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1.106 + EdgeMaps _edge_maps;
1.107 +
1.108 + typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1.109 + Attributes;
1.110 + Attributes _attributes;
1.111 +
1.112 + typedef std::map<std::string, _reader_bits::Section*> Sections;
1.113 + Sections _sections;
1.114 +
1.115 + bool _use_nodes;
1.116 + bool _use_edges;
1.117 +
1.118 + int line_num;
1.119 + std::istringstream line;
1.120 +
1.121 + public:
1.122 +
1.123 + /// \brief Constructor
1.124 + ///
1.125 + /// Construct a undirected graph reader, which reads from the given
1.126 + /// input stream.
1.127 + GraphReader(std::istream& is, Graph& graph)
1.128 + : _is(&is), local_is(false), _graph(graph),
1.129 + _use_nodes(false), _use_edges(false) {}
1.130 +
1.131 + /// \brief Constructor
1.132 + ///
1.133 + /// Construct a undirected graph reader, which reads from the given
1.134 + /// file.
1.135 + GraphReader(const std::string& fn, Graph& graph)
1.136 + : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1.137 + _use_nodes(false), _use_edges(false) {}
1.138 +
1.139 + /// \brief Constructor
1.140 + ///
1.141 + /// Construct a undirected graph reader, which reads from the given
1.142 + /// file.
1.143 + GraphReader(const char* fn, Graph& graph)
1.144 + : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1.145 + _use_nodes(false), _use_edges(false) {}
1.146 +
1.147 + /// \brief Copy constructor
1.148 + ///
1.149 + /// The copy constructor transfers all data from the other reader,
1.150 + /// therefore the copied reader will not be usable more.
1.151 + GraphReader(GraphReader& other)
1.152 + : _is(other._is), local_is(other.local_is), _graph(other._graph),
1.153 + _use_nodes(other._use_nodes), _use_edges(other._use_edges) {
1.154 +
1.155 + other._is = 0;
1.156 + other.local_is = false;
1.157 +
1.158 + _node_index.swap(other._node_index);
1.159 + _edge_index.swap(other._edge_index);
1.160 +
1.161 + _node_maps.swap(other._node_maps);
1.162 + _edge_maps.swap(other._edge_maps);
1.163 + _attributes.swap(other._attributes);
1.164 +
1.165 + _nodes_caption = other._nodes_caption;
1.166 + _edges_caption = other._edges_caption;
1.167 + _attributes_caption = other._attributes_caption;
1.168 +
1.169 + _sections.swap(other._sections);
1.170 + }
1.171 +
1.172 + /// \brief Destructor
1.173 + ~GraphReader() {
1.174 + for (typename NodeMaps::iterator it = _node_maps.begin();
1.175 + it != _node_maps.end(); ++it) {
1.176 + delete it->second;
1.177 + }
1.178 +
1.179 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
1.180 + it != _edge_maps.end(); ++it) {
1.181 + delete it->second;
1.182 + }
1.183 +
1.184 + for (typename Attributes::iterator it = _attributes.begin();
1.185 + it != _attributes.end(); ++it) {
1.186 + delete it->second;
1.187 + }
1.188 +
1.189 + for (typename Sections::iterator it = _sections.begin();
1.190 + it != _sections.end(); ++it) {
1.191 + delete it->second;
1.192 + }
1.193 +
1.194 + if (local_is) {
1.195 + delete _is;
1.196 + }
1.197 +
1.198 + }
1.199 +
1.200 + private:
1.201 +
1.202 + GraphReader& operator=(const GraphReader&);
1.203 +
1.204 + public:
1.205 +
1.206 + /// \name Reading rules
1.207 + /// @{
1.208 +
1.209 + /// \brief Node map reading rule
1.210 + ///
1.211 + /// Add a node map reading rule to the reader.
1.212 + template <typename Map>
1.213 + GraphReader& nodeMap(const std::string& caption, Map& map) {
1.214 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1.215 + _reader_bits::MapStorageBase<Node>* storage =
1.216 + new _reader_bits::MapStorage<Node, Map>(map);
1.217 + _node_maps.push_back(std::make_pair(caption, storage));
1.218 + return *this;
1.219 + }
1.220 +
1.221 + /// \brief Node map reading rule
1.222 + ///
1.223 + /// Add a node map reading rule with specialized converter to the
1.224 + /// reader.
1.225 + template <typename Map, typename Converter>
1.226 + GraphReader& nodeMap(const std::string& caption, Map& map,
1.227 + const Converter& converter = Converter()) {
1.228 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1.229 + _reader_bits::MapStorageBase<Node>* storage =
1.230 + new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1.231 + _node_maps.push_back(std::make_pair(caption, storage));
1.232 + return *this;
1.233 + }
1.234 +
1.235 + /// \brief Edge map reading rule
1.236 + ///
1.237 + /// Add an edge map reading rule to the reader.
1.238 + template <typename Map>
1.239 + GraphReader& edgeMap(const std::string& caption, Map& map) {
1.240 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1.241 + _reader_bits::MapStorageBase<Edge>* storage =
1.242 + new _reader_bits::MapStorage<Edge, Map>(map);
1.243 + _edge_maps.push_back(std::make_pair(caption, storage));
1.244 + return *this;
1.245 + }
1.246 +
1.247 + /// \brief Edge map reading rule
1.248 + ///
1.249 + /// Add an edge map reading rule with specialized converter to the
1.250 + /// reader.
1.251 + template <typename Map, typename Converter>
1.252 + GraphReader& edgeMap(const std::string& caption, Map& map,
1.253 + const Converter& converter = Converter()) {
1.254 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1.255 + _reader_bits::MapStorageBase<Edge>* storage =
1.256 + new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1.257 + _edge_maps.push_back(std::make_pair(caption, storage));
1.258 + return *this;
1.259 + }
1.260 +
1.261 + /// \brief Arc map reading rule
1.262 + ///
1.263 + /// Add an arc map reading rule to the reader.
1.264 + template <typename Map>
1.265 + GraphReader& arcMap(const std::string& caption, Map& map) {
1.266 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1.267 + _reader_bits::MapStorageBase<Edge>* forward_storage =
1.268 + new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1.269 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1.270 + _reader_bits::MapStorageBase<Edge>* backward_storage =
1.271 + new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1.272 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1.273 + return *this;
1.274 + }
1.275 +
1.276 + /// \brief Arc map reading rule
1.277 + ///
1.278 + /// Add an arc map reading rule with specialized converter to the
1.279 + /// reader.
1.280 + template <typename Map, typename Converter>
1.281 + GraphReader& arcMap(const std::string& caption, Map& map,
1.282 + const Converter& converter = Converter()) {
1.283 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1.284 + _reader_bits::MapStorageBase<Edge>* forward_storage =
1.285 + new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1.286 + (_graph, map, converter);
1.287 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1.288 + _reader_bits::MapStorageBase<Edge>* backward_storage =
1.289 + new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1.290 + (_graph, map, converter);
1.291 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1.292 + return *this;
1.293 + }
1.294 +
1.295 + /// \brief Attribute reading rule
1.296 + ///
1.297 + /// Add an attribute reading rule to the reader.
1.298 + template <typename Value>
1.299 + GraphReader& attribute(const std::string& caption, Value& value) {
1.300 + _reader_bits::ValueStorageBase* storage =
1.301 + new _reader_bits::ValueStorage<Value>(value);
1.302 + _attributes.insert(std::make_pair(caption, storage));
1.303 + return *this;
1.304 + }
1.305 +
1.306 + /// \brief Attribute reading rule
1.307 + ///
1.308 + /// Add an attribute reading rule with specialized converter to the
1.309 + /// reader.
1.310 + template <typename Value, typename Converter>
1.311 + GraphReader& attribute(const std::string& caption, Value& value,
1.312 + const Converter& converter = Converter()) {
1.313 + _reader_bits::ValueStorageBase* storage =
1.314 + new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1.315 + _attributes.insert(std::make_pair(caption, storage));
1.316 + return *this;
1.317 + }
1.318 +
1.319 + /// \brief Node reading rule
1.320 + ///
1.321 + /// Add a node reading rule to reader.
1.322 + GraphReader& node(const std::string& caption, Node& node) {
1.323 + typedef _reader_bits::MapLookUpConverter<Node> Converter;
1.324 + Converter converter(_node_index);
1.325 + _reader_bits::ValueStorageBase* storage =
1.326 + new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1.327 + _attributes.insert(std::make_pair(caption, storage));
1.328 + return *this;
1.329 + }
1.330 +
1.331 + /// \brief Edge reading rule
1.332 + ///
1.333 + /// Add an edge reading rule to reader.
1.334 + GraphReader& edge(const std::string& caption, Edge& edge) {
1.335 + typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1.336 + Converter converter(_edge_index);
1.337 + _reader_bits::ValueStorageBase* storage =
1.338 + new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1.339 + _attributes.insert(std::make_pair(caption, storage));
1.340 + return *this;
1.341 + }
1.342 +
1.343 + /// \brief Arc reading rule
1.344 + ///
1.345 + /// Add an arc reading rule to reader.
1.346 + GraphReader& arc(const std::string& caption, Arc& arc) {
1.347 + typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1.348 + Converter converter(_graph, _edge_index);
1.349 + _reader_bits::ValueStorageBase* storage =
1.350 + new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1.351 + _attributes.insert(std::make_pair(caption, storage));
1.352 + return *this;
1.353 + }
1.354 +
1.355 + /// @}
1.356 +
1.357 + /// \name Select section by name
1.358 + /// @{
1.359 +
1.360 + /// \brief Set \c \@nodes section to be read
1.361 + ///
1.362 + /// Set \c \@nodes section to be read
1.363 + GraphReader& nodes(const std::string& caption) {
1.364 + _nodes_caption = caption;
1.365 + return *this;
1.366 + }
1.367 +
1.368 + /// \brief Set \c \@edges section to be read
1.369 + ///
1.370 + /// Set \c \@edges section to be read
1.371 + GraphReader& edges(const std::string& caption) {
1.372 + _edges_caption = caption;
1.373 + return *this;
1.374 + }
1.375 +
1.376 + /// \brief Set \c \@attributes section to be read
1.377 + ///
1.378 + /// Set \c \@attributes section to be read
1.379 + GraphReader& attributes(const std::string& caption) {
1.380 + _attributes_caption = caption;
1.381 + return *this;
1.382 + }
1.383 +
1.384 + /// @}
1.385 +
1.386 + /// \name Section readers
1.387 + /// @{
1.388 +
1.389 + /// \brief Add a section processor with line oriented reading
1.390 + ///
1.391 + /// In the \e LGF file extra sections can be placed, which contain
1.392 + /// any data in arbitrary format. These sections can be read with
1.393 + /// this function line by line. The first parameter is the type
1.394 + /// descriptor of the section, the second is a functor, which
1.395 + /// takes just one \c std::string parameter. At the reading
1.396 + /// process, each line of the section will be given to the functor
1.397 + /// object. However, the empty lines and the comment lines are
1.398 + /// filtered out, and the leading whitespaces are stipped from
1.399 + /// each processed string.
1.400 + ///
1.401 + /// For example let's see a section, which contain several
1.402 + /// integers, which should be inserted into a vector.
1.403 + ///\code
1.404 + /// @numbers
1.405 + /// 12 45 23
1.406 + /// 4
1.407 + /// 23 6
1.408 + ///\endcode
1.409 + ///
1.410 + /// The functor is implemented as an struct:
1.411 + ///\code
1.412 + /// struct NumberSection {
1.413 + /// std::vector<int>& _data;
1.414 + /// NumberSection(std::vector<int>& data) : _data(data) {}
1.415 + /// void operator()(const std::string& line) {
1.416 + /// std::istringstream ls(line);
1.417 + /// int value;
1.418 + /// while (ls >> value) _data.push_back(value);
1.419 + /// }
1.420 + /// };
1.421 + ///
1.422 + /// // ...
1.423 + ///
1.424 + /// reader.sectionLines("numbers", NumberSection(vec));
1.425 + ///\endcode
1.426 + template <typename Functor>
1.427 + GraphReader& sectionLines(const std::string& type, Functor functor) {
1.428 + LEMON_ASSERT(!type.empty(), "Type is not empty.");
1.429 + LEMON_ASSERT(_sections.find(type) == _sections.end(),
1.430 + "Multiple reading of section.");
1.431 + LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1.432 + type != "attributes", "Multiple reading of section.");
1.433 + _sections.insert(std::make_pair(type,
1.434 + new _reader_bits::LineSection<Functor>(functor)));
1.435 + return *this;
1.436 + }
1.437 +
1.438 +
1.439 + /// \brief Add a section processor with stream oriented reading
1.440 + ///
1.441 + /// In the \e LGF file extra sections can be placed, which contain
1.442 + /// any data in arbitrary format. These sections can be read
1.443 + /// directly with this function. The first parameter is the type
1.444 + /// of the section, the second is a functor, which takes an \c
1.445 + /// std::istream& and an int& parameter, the latter regard to the
1.446 + /// line number of stream. The functor can read the input while
1.447 + /// the section go on, and the line number should be modified
1.448 + /// accordingly.
1.449 + template <typename Functor>
1.450 + GraphReader& sectionStream(const std::string& type, Functor functor) {
1.451 + LEMON_ASSERT(!type.empty(), "Type is not empty.");
1.452 + LEMON_ASSERT(_sections.find(type) == _sections.end(),
1.453 + "Multiple reading of section.");
1.454 + LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1.455 + type != "attributes", "Multiple reading of section.");
1.456 + _sections.insert(std::make_pair(type,
1.457 + new _reader_bits::StreamSection<Functor>(functor)));
1.458 + return *this;
1.459 + }
1.460 +
1.461 + /// @}
1.462 +
1.463 + /// \name Using previously constructed node or edge set
1.464 + /// @{
1.465 +
1.466 + /// \brief Use previously constructed node set
1.467 + ///
1.468 + /// Use previously constructed node set, and specify the node
1.469 + /// label map.
1.470 + template <typename Map>
1.471 + GraphReader& useNodes(const Map& map) {
1.472 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.473 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1.474 + _use_nodes = true;
1.475 + _writer_bits::DefaultConverter<typename Map::Value> converter;
1.476 + for (NodeIt n(_graph); n != INVALID; ++n) {
1.477 + _node_index.insert(std::make_pair(converter(map[n]), n));
1.478 + }
1.479 + return *this;
1.480 + }
1.481 +
1.482 + /// \brief Use previously constructed node set
1.483 + ///
1.484 + /// Use previously constructed node set, and specify the node
1.485 + /// label map and a functor which converts the label map values to
1.486 + /// std::string.
1.487 + template <typename Map, typename Converter>
1.488 + GraphReader& useNodes(const Map& map,
1.489 + const Converter& converter = Converter()) {
1.490 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.491 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1.492 + _use_nodes = true;
1.493 + for (NodeIt n(_graph); n != INVALID; ++n) {
1.494 + _node_index.insert(std::make_pair(converter(map[n]), n));
1.495 + }
1.496 + return *this;
1.497 + }
1.498 +
1.499 + /// \brief Use previously constructed edge set
1.500 + ///
1.501 + /// Use previously constructed edge set, and specify the edge
1.502 + /// label map.
1.503 + template <typename Map>
1.504 + GraphReader& useEdges(const Map& map) {
1.505 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1.506 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1.507 + _use_edges = true;
1.508 + _writer_bits::DefaultConverter<typename Map::Value> converter;
1.509 + for (EdgeIt a(_graph); a != INVALID; ++a) {
1.510 + _edge_index.insert(std::make_pair(converter(map[a]), a));
1.511 + }
1.512 + return *this;
1.513 + }
1.514 +
1.515 + /// \brief Use previously constructed edge set
1.516 + ///
1.517 + /// Use previously constructed edge set, and specify the edge
1.518 + /// label map and a functor which converts the label map values to
1.519 + /// std::string.
1.520 + template <typename Map, typename Converter>
1.521 + GraphReader& useEdges(const Map& map,
1.522 + const Converter& converter = Converter()) {
1.523 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1.524 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1.525 + _use_edges = true;
1.526 + for (EdgeIt a(_graph); a != INVALID; ++a) {
1.527 + _edge_index.insert(std::make_pair(converter(map[a]), a));
1.528 + }
1.529 + return *this;
1.530 + }
1.531 +
1.532 + /// @}
1.533 +
1.534 + private:
1.535 +
1.536 + bool readLine() {
1.537 + std::string str;
1.538 + while(++line_num, std::getline(*_is, str)) {
1.539 + line.clear(); line.str(str);
1.540 + char c;
1.541 + if (line >> std::ws >> c && c != '#') {
1.542 + line.putback(c);
1.543 + return true;
1.544 + }
1.545 + }
1.546 + return false;
1.547 + }
1.548 +
1.549 + bool readSuccess() {
1.550 + return static_cast<bool>(*_is);
1.551 + }
1.552 +
1.553 + void skipSection() {
1.554 + char c;
1.555 + while (readSuccess() && line >> c && c != '@') {
1.556 + readLine();
1.557 + }
1.558 + line.putback(c);
1.559 + }
1.560 +
1.561 + void readNodes() {
1.562 +
1.563 + std::vector<int> map_index(_node_maps.size());
1.564 + int map_num, label_index;
1.565 +
1.566 + if (!readLine())
1.567 + throw DataFormatError("Cannot find map captions");
1.568 +
1.569 + {
1.570 + std::map<std::string, int> maps;
1.571 +
1.572 + std::string map;
1.573 + int index = 0;
1.574 + while (_reader_bits::readToken(line, map)) {
1.575 + if (maps.find(map) != maps.end()) {
1.576 + std::ostringstream msg;
1.577 + msg << "Multiple occurence of node map: " << map;
1.578 + throw DataFormatError(msg.str().c_str());
1.579 + }
1.580 + maps.insert(std::make_pair(map, index));
1.581 + ++index;
1.582 + }
1.583 +
1.584 + for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1.585 + std::map<std::string, int>::iterator jt =
1.586 + maps.find(_node_maps[i].first);
1.587 + if (jt == maps.end()) {
1.588 + std::ostringstream msg;
1.589 + msg << "Map not found in file: " << _node_maps[i].first;
1.590 + throw DataFormatError(msg.str().c_str());
1.591 + }
1.592 + map_index[i] = jt->second;
1.593 + }
1.594 +
1.595 + {
1.596 + std::map<std::string, int>::iterator jt = maps.find("label");
1.597 + if (jt == maps.end())
1.598 + throw DataFormatError("Label map not found in file");
1.599 + label_index = jt->second;
1.600 + }
1.601 + map_num = maps.size();
1.602 + }
1.603 +
1.604 + char c;
1.605 + while (readLine() && line >> c && c != '@') {
1.606 + line.putback(c);
1.607 +
1.608 + std::vector<std::string> tokens(map_num);
1.609 + for (int i = 0; i < map_num; ++i) {
1.610 + if (!_reader_bits::readToken(line, tokens[i])) {
1.611 + std::ostringstream msg;
1.612 + msg << "Column not found (" << i + 1 << ")";
1.613 + throw DataFormatError(msg.str().c_str());
1.614 + }
1.615 + }
1.616 + if (line >> std::ws >> c)
1.617 + throw DataFormatError("Extra character on the end of line");
1.618 +
1.619 + Node n;
1.620 + if (!_use_nodes) {
1.621 + n = _graph.addNode();
1.622 + _node_index.insert(std::make_pair(tokens[label_index], n));
1.623 + } else {
1.624 + typename std::map<std::string, Node>::iterator it =
1.625 + _node_index.find(tokens[label_index]);
1.626 + if (it == _node_index.end()) {
1.627 + std::ostringstream msg;
1.628 + msg << "Node with label not found: " << tokens[label_index];
1.629 + throw DataFormatError(msg.str().c_str());
1.630 + }
1.631 + n = it->second;
1.632 + }
1.633 +
1.634 + for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1.635 + _node_maps[i].second->set(n, tokens[map_index[i]]);
1.636 + }
1.637 +
1.638 + }
1.639 + if (readSuccess()) {
1.640 + line.putback(c);
1.641 + }
1.642 + }
1.643 +
1.644 + void readEdges() {
1.645 +
1.646 + std::vector<int> map_index(_edge_maps.size());
1.647 + int map_num, label_index;
1.648 +
1.649 + if (!readLine())
1.650 + throw DataFormatError("Cannot find map captions");
1.651 +
1.652 + {
1.653 + std::map<std::string, int> maps;
1.654 +
1.655 + std::string map;
1.656 + int index = 0;
1.657 + while (_reader_bits::readToken(line, map)) {
1.658 + if (maps.find(map) != maps.end()) {
1.659 + std::ostringstream msg;
1.660 + msg << "Multiple occurence of edge map: " << map;
1.661 + throw DataFormatError(msg.str().c_str());
1.662 + }
1.663 + maps.insert(std::make_pair(map, index));
1.664 + ++index;
1.665 + }
1.666 +
1.667 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1.668 + std::map<std::string, int>::iterator jt =
1.669 + maps.find(_edge_maps[i].first);
1.670 + if (jt == maps.end()) {
1.671 + std::ostringstream msg;
1.672 + msg << "Map not found in file: " << _edge_maps[i].first;
1.673 + throw DataFormatError(msg.str().c_str());
1.674 + }
1.675 + map_index[i] = jt->second;
1.676 + }
1.677 +
1.678 + {
1.679 + std::map<std::string, int>::iterator jt = maps.find("label");
1.680 + if (jt == maps.end())
1.681 + throw DataFormatError("Label map not found in file");
1.682 + label_index = jt->second;
1.683 + }
1.684 + map_num = maps.size();
1.685 + }
1.686 +
1.687 + char c;
1.688 + while (readLine() && line >> c && c != '@') {
1.689 + line.putback(c);
1.690 +
1.691 + std::string source_token;
1.692 + std::string target_token;
1.693 +
1.694 + if (!_reader_bits::readToken(line, source_token))
1.695 + throw DataFormatError("Source not found");
1.696 +
1.697 + if (!_reader_bits::readToken(line, target_token))
1.698 + throw DataFormatError("Source not found");
1.699 +
1.700 + std::vector<std::string> tokens(map_num);
1.701 + for (int i = 0; i < map_num; ++i) {
1.702 + if (!_reader_bits::readToken(line, tokens[i])) {
1.703 + std::ostringstream msg;
1.704 + msg << "Column not found (" << i + 1 << ")";
1.705 + throw DataFormatError(msg.str().c_str());
1.706 + }
1.707 + }
1.708 + if (line >> std::ws >> c)
1.709 + throw DataFormatError("Extra character on the end of line");
1.710 +
1.711 + Edge e;
1.712 + if (!_use_edges) {
1.713 +
1.714 + typename NodeIndex::iterator it;
1.715 +
1.716 + it = _node_index.find(source_token);
1.717 + if (it == _node_index.end()) {
1.718 + std::ostringstream msg;
1.719 + msg << "Item not found: " << source_token;
1.720 + throw DataFormatError(msg.str().c_str());
1.721 + }
1.722 + Node source = it->second;
1.723 +
1.724 + it = _node_index.find(target_token);
1.725 + if (it == _node_index.end()) {
1.726 + std::ostringstream msg;
1.727 + msg << "Item not found: " << target_token;
1.728 + throw DataFormatError(msg.str().c_str());
1.729 + }
1.730 + Node target = it->second;
1.731 +
1.732 + e = _graph.addEdge(source, target);
1.733 + _edge_index.insert(std::make_pair(tokens[label_index], e));
1.734 + } else {
1.735 + typename std::map<std::string, Edge>::iterator it =
1.736 + _edge_index.find(tokens[label_index]);
1.737 + if (it == _edge_index.end()) {
1.738 + std::ostringstream msg;
1.739 + msg << "Edge with label not found: " << tokens[label_index];
1.740 + throw DataFormatError(msg.str().c_str());
1.741 + }
1.742 + e = it->second;
1.743 + }
1.744 +
1.745 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1.746 + _edge_maps[i].second->set(e, tokens[map_index[i]]);
1.747 + }
1.748 +
1.749 + }
1.750 + if (readSuccess()) {
1.751 + line.putback(c);
1.752 + }
1.753 + }
1.754 +
1.755 + void readAttributes() {
1.756 +
1.757 + std::set<std::string> read_attr;
1.758 +
1.759 + char c;
1.760 + while (readLine() && line >> c && c != '@') {
1.761 + line.putback(c);
1.762 +
1.763 + std::string attr, token;
1.764 + if (!_reader_bits::readToken(line, attr))
1.765 + throw DataFormatError("Attribute name not found");
1.766 + if (!_reader_bits::readToken(line, token))
1.767 + throw DataFormatError("Attribute value not found");
1.768 + if (line >> c)
1.769 + throw DataFormatError("Extra character on the end of line");
1.770 +
1.771 + {
1.772 + std::set<std::string>::iterator it = read_attr.find(attr);
1.773 + if (it != read_attr.end()) {
1.774 + std::ostringstream msg;
1.775 + msg << "Multiple occurence of attribute " << attr;
1.776 + throw DataFormatError(msg.str().c_str());
1.777 + }
1.778 + read_attr.insert(attr);
1.779 + }
1.780 +
1.781 + {
1.782 + typename Attributes::iterator it = _attributes.lower_bound(attr);
1.783 + while (it != _attributes.end() && it->first == attr) {
1.784 + it->second->set(token);
1.785 + ++it;
1.786 + }
1.787 + }
1.788 +
1.789 + }
1.790 + if (readSuccess()) {
1.791 + line.putback(c);
1.792 + }
1.793 + for (typename Attributes::iterator it = _attributes.begin();
1.794 + it != _attributes.end(); ++it) {
1.795 + if (read_attr.find(it->first) == read_attr.end()) {
1.796 + std::ostringstream msg;
1.797 + msg << "Attribute not found in file: " << it->first;
1.798 + throw DataFormatError(msg.str().c_str());
1.799 + }
1.800 + }
1.801 + }
1.802 +
1.803 + public:
1.804 +
1.805 + /// \name Execution of the reader
1.806 + /// @{
1.807 +
1.808 + /// \brief Start the batch processing
1.809 + ///
1.810 + /// This function starts the batch processing
1.811 + void run() {
1.812 +
1.813 + LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1.814 +
1.815 + bool nodes_done = false;
1.816 + bool edges_done = false;
1.817 + bool attributes_done = false;
1.818 + std::set<std::string> extra_sections;
1.819 +
1.820 + line_num = 0;
1.821 + readLine();
1.822 +
1.823 + while (readSuccess()) {
1.824 + skipSection();
1.825 + try {
1.826 + char c;
1.827 + std::string section, caption;
1.828 + line >> c;
1.829 + _reader_bits::readToken(line, section);
1.830 + _reader_bits::readToken(line, caption);
1.831 +
1.832 + if (line >> c)
1.833 + throw DataFormatError("Extra character on the end of line");
1.834 +
1.835 + if (section == "nodes" && !nodes_done) {
1.836 + if (_nodes_caption.empty() || _nodes_caption == caption) {
1.837 + readNodes();
1.838 + nodes_done = true;
1.839 + }
1.840 + } else if ((section == "edges" || section == "arcs") &&
1.841 + !edges_done) {
1.842 + if (_edges_caption.empty() || _edges_caption == caption) {
1.843 + readEdges();
1.844 + edges_done = true;
1.845 + }
1.846 + } else if (section == "attributes" && !attributes_done) {
1.847 + if (_attributes_caption.empty() || _attributes_caption == caption) {
1.848 + readAttributes();
1.849 + attributes_done = true;
1.850 + }
1.851 + } else {
1.852 + if (extra_sections.find(section) != extra_sections.end()) {
1.853 + std::ostringstream msg;
1.854 + msg << "Multiple occurence of section " << section;
1.855 + throw DataFormatError(msg.str().c_str());
1.856 + }
1.857 + Sections::iterator it = _sections.find(section);
1.858 + if (it != _sections.end()) {
1.859 + extra_sections.insert(section);
1.860 + it->second->process(*_is, line_num);
1.861 + readLine();
1.862 + } else {
1.863 + readLine();
1.864 + skipSection();
1.865 + }
1.866 + }
1.867 + } catch (DataFormatError& error) {
1.868 + error.line(line_num);
1.869 + throw;
1.870 + }
1.871 + }
1.872 +
1.873 + if (!nodes_done) {
1.874 + throw DataFormatError("Section @nodes not found");
1.875 + }
1.876 +
1.877 + if (!edges_done) {
1.878 + throw DataFormatError("Section @edges not found");
1.879 + }
1.880 +
1.881 + if (!attributes_done && !_attributes.empty()) {
1.882 + throw DataFormatError("Section @attributes not found");
1.883 + }
1.884 +
1.885 + }
1.886 +
1.887 + /// @}
1.888 +
1.889 + };
1.890 +
1.891 + /// \relates GraphReader
1.892 + template <typename Graph>
1.893 + GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
1.894 + GraphReader<Graph> tmp(is, graph);
1.895 + return tmp;
1.896 + }
1.897 +
1.898 + /// \relates GraphReader
1.899 + template <typename Graph>
1.900 + GraphReader<Graph> graphReader(const std::string& fn,
1.901 + Graph& graph) {
1.902 + GraphReader<Graph> tmp(fn, graph);
1.903 + return tmp;
1.904 + }
1.905 +
1.906 + /// \relates GraphReader
1.907 + template <typename Graph>
1.908 + GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
1.909 + GraphReader<Graph> tmp(fn, graph);
1.910 + return tmp;
1.911 + }
1.912 }
1.913
1.914 #endif
2.1 --- a/lemon/lgf_writer.h Sat May 31 12:34:44 2008 +0200
2.2 +++ b/lemon/lgf_writer.h Sat May 31 12:49:18 2008 +0200
2.3 @@ -71,6 +71,27 @@
2.4 }
2.5 };
2.6
2.7 + template <typename _Graph, bool _dir, typename _Map>
2.8 + class GraphArcMapLess {
2.9 + public:
2.10 + typedef _Map Map;
2.11 + typedef _Graph Graph;
2.12 + typedef typename Graph::Edge Item;
2.13 +
2.14 + private:
2.15 + const Graph& _graph;
2.16 + const Map& _map;
2.17 +
2.18 + public:
2.19 + GraphArcMapLess(const Graph& graph, const Map& map)
2.20 + : _graph(graph), _map(map) {}
2.21 +
2.22 + bool operator()(const Item& left, const Item& right) {
2.23 + return _map[_graph.direct(left, _dir)] <
2.24 + _map[_graph.direct(right, _dir)];
2.25 + }
2.26 + };
2.27 +
2.28 template <typename _Item>
2.29 class MapStorageBase {
2.30 public:
2.31 @@ -110,6 +131,36 @@
2.32 }
2.33 };
2.34
2.35 + template <typename _Graph, bool _dir, typename _Map,
2.36 + typename _Converter = DefaultConverter<typename _Map::Value> >
2.37 + class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
2.38 + public:
2.39 + typedef _Map Map;
2.40 + typedef _Converter Converter;
2.41 + typedef _Graph Graph;
2.42 + typedef typename Graph::Edge Item;
2.43 + static const bool dir = _dir;
2.44 +
2.45 + private:
2.46 + const Graph& _graph;
2.47 + const Map& _map;
2.48 + Converter _converter;
2.49 +
2.50 + public:
2.51 + GraphArcMapStorage(const Graph& graph, const Map& map,
2.52 + const Converter& converter = Converter())
2.53 + : _graph(graph), _map(map), _converter(converter) {}
2.54 + virtual ~GraphArcMapStorage() {}
2.55 +
2.56 + virtual std::string get(const Item& item) {
2.57 + return _converter(_map[_graph.direct(item, dir)]);
2.58 + }
2.59 + virtual void sort(std::vector<Item>& items) {
2.60 + GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
2.61 + std::sort(items.begin(), items.end(), less);
2.62 + }
2.63 + };
2.64 +
2.65 class ValueStorageBase {
2.66 public:
2.67 ValueStorageBase() {}
2.68 @@ -154,6 +205,26 @@
2.69 }
2.70 };
2.71
2.72 + template <typename Graph>
2.73 + struct GraphArcLookUpConverter {
2.74 + const Graph& _graph;
2.75 + const std::map<typename Graph::Edge, std::string>& _map;
2.76 +
2.77 + GraphArcLookUpConverter(const Graph& graph,
2.78 + const std::map<typename Graph::Edge,
2.79 + std::string>& map)
2.80 + : _graph(graph), _map(map) {}
2.81 +
2.82 + std::string operator()(const typename Graph::Arc& val) {
2.83 + typename std::map<typename Graph::Edge, std::string>
2.84 + ::const_iterator it = _map.find(val);
2.85 + if (it == _map.end()) {
2.86 + throw DataFormatError("Item not found");
2.87 + }
2.88 + return (_graph.direction(val) ? '+' : '-') + it->second;
2.89 + }
2.90 + };
2.91 +
2.92 bool isWhiteSpace(char c) {
2.93 return c == ' ' || c == '\t' || c == '\v' ||
2.94 c == '\n' || c == '\r' || c == '\f';
2.95 @@ -738,6 +809,517 @@
2.96 DigraphWriter<Digraph> tmp(fn, digraph);
2.97 return tmp;
2.98 }
2.99 +
2.100 + /// \ingroup lemon_io
2.101 + ///
2.102 + /// \brief LGF writer for directed graphs
2.103 + ///
2.104 + /// This utility writes an \ref lgf-format "LGF" file.
2.105 + template <typename _Graph>
2.106 + class GraphWriter {
2.107 + public:
2.108 +
2.109 + typedef _Graph Graph;
2.110 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
2.111 +
2.112 + private:
2.113 +
2.114 +
2.115 + std::ostream* _os;
2.116 + bool local_os;
2.117 +
2.118 + Graph& _graph;
2.119 +
2.120 + std::string _nodes_caption;
2.121 + std::string _edges_caption;
2.122 + std::string _attributes_caption;
2.123 +
2.124 + typedef std::map<Node, std::string> NodeIndex;
2.125 + NodeIndex _node_index;
2.126 + typedef std::map<Edge, std::string> EdgeIndex;
2.127 + EdgeIndex _edge_index;
2.128 +
2.129 + typedef std::vector<std::pair<std::string,
2.130 + _writer_bits::MapStorageBase<Node>* > > NodeMaps;
2.131 + NodeMaps _node_maps;
2.132 +
2.133 + typedef std::vector<std::pair<std::string,
2.134 + _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
2.135 + EdgeMaps _edge_maps;
2.136 +
2.137 + typedef std::vector<std::pair<std::string,
2.138 + _writer_bits::ValueStorageBase*> > Attributes;
2.139 + Attributes _attributes;
2.140 +
2.141 + bool _skip_nodes;
2.142 + bool _skip_edges;
2.143 +
2.144 + public:
2.145 +
2.146 + /// \brief Constructor
2.147 + ///
2.148 + /// Construct a directed graph writer, which writes to the given
2.149 + /// output stream.
2.150 + GraphWriter(std::ostream& is, Graph& graph)
2.151 + : _os(&is), local_os(false), _graph(graph),
2.152 + _skip_nodes(false), _skip_edges(false) {}
2.153 +
2.154 + /// \brief Constructor
2.155 + ///
2.156 + /// Construct a directed graph writer, which writes to the given
2.157 + /// output file.
2.158 + GraphWriter(const std::string& fn, Graph& graph)
2.159 + : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
2.160 + _skip_nodes(false), _skip_edges(false) {}
2.161 +
2.162 + /// \brief Constructor
2.163 + ///
2.164 + /// Construct a directed graph writer, which writes to the given
2.165 + /// output file.
2.166 + GraphWriter(const char* fn, Graph& graph)
2.167 + : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
2.168 + _skip_nodes(false), _skip_edges(false) {}
2.169 +
2.170 + /// \brief Copy constructor
2.171 + ///
2.172 + /// The copy constructor transfers all data from the other writer,
2.173 + /// therefore the copied writer will not be usable more.
2.174 + GraphWriter(GraphWriter& other)
2.175 + : _os(other._os), local_os(other.local_os), _graph(other._graph),
2.176 + _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
2.177 +
2.178 + other._os = 0;
2.179 + other.local_os = false;
2.180 +
2.181 + _node_index.swap(other._node_index);
2.182 + _edge_index.swap(other._edge_index);
2.183 +
2.184 + _node_maps.swap(other._node_maps);
2.185 + _edge_maps.swap(other._edge_maps);
2.186 + _attributes.swap(other._attributes);
2.187 +
2.188 + _nodes_caption = other._nodes_caption;
2.189 + _edges_caption = other._edges_caption;
2.190 + _attributes_caption = other._attributes_caption;
2.191 + }
2.192 +
2.193 + /// \brief Destructor
2.194 + ~GraphWriter() {
2.195 + for (typename NodeMaps::iterator it = _node_maps.begin();
2.196 + it != _node_maps.end(); ++it) {
2.197 + delete it->second;
2.198 + }
2.199 +
2.200 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
2.201 + it != _edge_maps.end(); ++it) {
2.202 + delete it->second;
2.203 + }
2.204 +
2.205 + for (typename Attributes::iterator it = _attributes.begin();
2.206 + it != _attributes.end(); ++it) {
2.207 + delete it->second;
2.208 + }
2.209 +
2.210 + if (local_os) {
2.211 + delete _os;
2.212 + }
2.213 + }
2.214 +
2.215 + private:
2.216 +
2.217 + GraphWriter& operator=(const GraphWriter&);
2.218 +
2.219 + public:
2.220 +
2.221 + /// \name Writing rules
2.222 + /// @{
2.223 +
2.224 + /// \brief Node map reading rule
2.225 + ///
2.226 + /// Add a node map reading rule to the writer.
2.227 + template <typename Map>
2.228 + GraphWriter& nodeMap(const std::string& caption, const Map& map) {
2.229 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
2.230 + _writer_bits::MapStorageBase<Node>* storage =
2.231 + new _writer_bits::MapStorage<Node, Map>(map);
2.232 + _node_maps.push_back(std::make_pair(caption, storage));
2.233 + return *this;
2.234 + }
2.235 +
2.236 + /// \brief Node map writing rule
2.237 + ///
2.238 + /// Add a node map writing rule with specialized converter to the
2.239 + /// writer.
2.240 + template <typename Map, typename Converter>
2.241 + GraphWriter& nodeMap(const std::string& caption, const Map& map,
2.242 + const Converter& converter = Converter()) {
2.243 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
2.244 + _writer_bits::MapStorageBase<Node>* storage =
2.245 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
2.246 + _node_maps.push_back(std::make_pair(caption, storage));
2.247 + return *this;
2.248 + }
2.249 +
2.250 + /// \brief Edge map writing rule
2.251 + ///
2.252 + /// Add an edge map writing rule to the writer.
2.253 + template <typename Map>
2.254 + GraphWriter& edgeMap(const std::string& caption, const Map& map) {
2.255 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
2.256 + _writer_bits::MapStorageBase<Edge>* storage =
2.257 + new _writer_bits::MapStorage<Edge, Map>(map);
2.258 + _edge_maps.push_back(std::make_pair(caption, storage));
2.259 + return *this;
2.260 + }
2.261 +
2.262 + /// \brief Edge map writing rule
2.263 + ///
2.264 + /// Add an edge map writing rule with specialized converter to the
2.265 + /// writer.
2.266 + template <typename Map, typename Converter>
2.267 + GraphWriter& edgeMap(const std::string& caption, const Map& map,
2.268 + const Converter& converter = Converter()) {
2.269 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
2.270 + _writer_bits::MapStorageBase<Edge>* storage =
2.271 + new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
2.272 + _edge_maps.push_back(std::make_pair(caption, storage));
2.273 + return *this;
2.274 + }
2.275 +
2.276 + /// \brief Arc map writing rule
2.277 + ///
2.278 + /// Add an arc map writing rule to the writer.
2.279 + template <typename Map>
2.280 + GraphWriter& arcMap(const std::string& caption, const Map& map) {
2.281 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
2.282 + _writer_bits::MapStorageBase<Edge>* forward_storage =
2.283 + new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
2.284 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
2.285 + _writer_bits::MapStorageBase<Edge>* backward_storage =
2.286 + new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
2.287 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
2.288 + return *this;
2.289 + }
2.290 +
2.291 + /// \brief Arc map writing rule
2.292 + ///
2.293 + /// Add an arc map writing rule with specialized converter to the
2.294 + /// writer.
2.295 + template <typename Map, typename Converter>
2.296 + GraphWriter& arcMap(const std::string& caption, const Map& map,
2.297 + const Converter& converter = Converter()) {
2.298 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
2.299 + _writer_bits::MapStorageBase<Edge>* forward_storage =
2.300 + new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
2.301 + (_graph, map, converter);
2.302 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
2.303 + _writer_bits::MapStorageBase<Edge>* backward_storage =
2.304 + new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
2.305 + (_graph, map, converter);
2.306 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
2.307 + return *this;
2.308 + }
2.309 +
2.310 + /// \brief Attribute writing rule
2.311 + ///
2.312 + /// Add an attribute writing rule to the writer.
2.313 + template <typename Value>
2.314 + GraphWriter& attribute(const std::string& caption, const Value& value) {
2.315 + _writer_bits::ValueStorageBase* storage =
2.316 + new _writer_bits::ValueStorage<Value>(value);
2.317 + _attributes.push_back(std::make_pair(caption, storage));
2.318 + return *this;
2.319 + }
2.320 +
2.321 + /// \brief Attribute writing rule
2.322 + ///
2.323 + /// Add an attribute writing rule with specialized converter to the
2.324 + /// writer.
2.325 + template <typename Value, typename Converter>
2.326 + GraphWriter& attribute(const std::string& caption, const Value& value,
2.327 + const Converter& converter = Converter()) {
2.328 + _writer_bits::ValueStorageBase* storage =
2.329 + new _writer_bits::ValueStorage<Value, Converter>(value, converter);
2.330 + _attributes.push_back(std::make_pair(caption, storage));
2.331 + return *this;
2.332 + }
2.333 +
2.334 + /// \brief Node writing rule
2.335 + ///
2.336 + /// Add a node writing rule to the writer.
2.337 + GraphWriter& node(const std::string& caption, const Node& node) {
2.338 + typedef _writer_bits::MapLookUpConverter<Node> Converter;
2.339 + Converter converter(_node_index);
2.340 + _writer_bits::ValueStorageBase* storage =
2.341 + new _writer_bits::ValueStorage<Node, Converter>(node, converter);
2.342 + _attributes.push_back(std::make_pair(caption, storage));
2.343 + return *this;
2.344 + }
2.345 +
2.346 + /// \brief Edge writing rule
2.347 + ///
2.348 + /// Add an edge writing rule to writer.
2.349 + GraphWriter& edge(const std::string& caption, const Edge& edge) {
2.350 + typedef _writer_bits::MapLookUpConverter<Edge> Converter;
2.351 + Converter converter(_edge_index);
2.352 + _writer_bits::ValueStorageBase* storage =
2.353 + new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
2.354 + _attributes.push_back(std::make_pair(caption, storage));
2.355 + return *this;
2.356 + }
2.357 +
2.358 + /// \brief Arc writing rule
2.359 + ///
2.360 + /// Add an arc writing rule to writer.
2.361 + GraphWriter& arc(const std::string& caption, const Arc& arc) {
2.362 + typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
2.363 + Converter converter(_graph, _edge_index);
2.364 + _writer_bits::ValueStorageBase* storage =
2.365 + new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
2.366 + _attributes.push_back(std::make_pair(caption, storage));
2.367 + return *this;
2.368 + }
2.369 +
2.370 + /// \name Select section by name
2.371 + /// @{
2.372 +
2.373 + /// \brief Set \c \@nodes section to be read
2.374 + ///
2.375 + /// Set \c \@nodes section to be read
2.376 + GraphWriter& nodes(const std::string& caption) {
2.377 + _nodes_caption = caption;
2.378 + return *this;
2.379 + }
2.380 +
2.381 + /// \brief Set \c \@edges section to be read
2.382 + ///
2.383 + /// Set \c \@edges section to be read
2.384 + GraphWriter& edges(const std::string& caption) {
2.385 + _edges_caption = caption;
2.386 + return *this;
2.387 + }
2.388 +
2.389 + /// \brief Set \c \@attributes section to be read
2.390 + ///
2.391 + /// Set \c \@attributes section to be read
2.392 + GraphWriter& attributes(const std::string& caption) {
2.393 + _attributes_caption = caption;
2.394 + return *this;
2.395 + }
2.396 +
2.397 + /// \name Skipping section
2.398 + /// @{
2.399 +
2.400 + /// \brief Skip writing the node set
2.401 + ///
2.402 + /// The \c \@nodes section will be not written to the stream.
2.403 + GraphWriter& skipNodes() {
2.404 + LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
2.405 + return *this;
2.406 + }
2.407 +
2.408 + /// \brief Skip writing edge set
2.409 + ///
2.410 + /// The \c \@edges section will be not written to the stream.
2.411 + GraphWriter& skipEdges() {
2.412 + LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
2.413 + return *this;
2.414 + }
2.415 +
2.416 + /// @}
2.417 +
2.418 + private:
2.419 +
2.420 + void writeNodes() {
2.421 + _writer_bits::MapStorageBase<Node>* label = 0;
2.422 + for (typename NodeMaps::iterator it = _node_maps.begin();
2.423 + it != _node_maps.end(); ++it) {
2.424 + if (it->first == "label") {
2.425 + label = it->second;
2.426 + break;
2.427 + }
2.428 + }
2.429 +
2.430 + *_os << "@nodes";
2.431 + if (!_nodes_caption.empty()) {
2.432 + _writer_bits::writeToken(*_os << ' ', _nodes_caption);
2.433 + }
2.434 + *_os << std::endl;
2.435 +
2.436 + if (label == 0) {
2.437 + *_os << "label" << '\t';
2.438 + }
2.439 + for (typename NodeMaps::iterator it = _node_maps.begin();
2.440 + it != _node_maps.end(); ++it) {
2.441 + _writer_bits::writeToken(*_os, it->first) << '\t';
2.442 + }
2.443 + *_os << std::endl;
2.444 +
2.445 + std::vector<Node> nodes;
2.446 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.447 + nodes.push_back(n);
2.448 + }
2.449 +
2.450 + if (label == 0) {
2.451 + IdMap<Graph, Node> id_map(_graph);
2.452 + _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
2.453 + std::sort(nodes.begin(), nodes.end(), id_less);
2.454 + } else {
2.455 + label->sort(nodes);
2.456 + }
2.457 +
2.458 + for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
2.459 + Node n = nodes[i];
2.460 + if (label == 0) {
2.461 + std::ostringstream os;
2.462 + os << _graph.id(n);
2.463 + _writer_bits::writeToken(*_os, os.str());
2.464 + *_os << '\t';
2.465 + _node_index.insert(std::make_pair(n, os.str()));
2.466 + }
2.467 + for (typename NodeMaps::iterator it = _node_maps.begin();
2.468 + it != _node_maps.end(); ++it) {
2.469 + std::string value = it->second->get(n);
2.470 + _writer_bits::writeToken(*_os, value);
2.471 + if (it->first == "label") {
2.472 + _node_index.insert(std::make_pair(n, value));
2.473 + }
2.474 + *_os << '\t';
2.475 + }
2.476 + *_os << std::endl;
2.477 + }
2.478 + }
2.479 +
2.480 + void writeEdges() {
2.481 + _writer_bits::MapStorageBase<Edge>* label = 0;
2.482 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
2.483 + it != _edge_maps.end(); ++it) {
2.484 + if (it->first == "label") {
2.485 + label = it->second;
2.486 + break;
2.487 + }
2.488 + }
2.489 +
2.490 + *_os << "@edges";
2.491 + if (!_edges_caption.empty()) {
2.492 + _writer_bits::writeToken(*_os << ' ', _edges_caption);
2.493 + }
2.494 + *_os << std::endl;
2.495 +
2.496 + *_os << '\t' << '\t';
2.497 + if (label == 0) {
2.498 + *_os << "label" << '\t';
2.499 + }
2.500 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
2.501 + it != _edge_maps.end(); ++it) {
2.502 + _writer_bits::writeToken(*_os, it->first) << '\t';
2.503 + }
2.504 + *_os << std::endl;
2.505 +
2.506 + std::vector<Edge> edges;
2.507 + for (EdgeIt n(_graph); n != INVALID; ++n) {
2.508 + edges.push_back(n);
2.509 + }
2.510 +
2.511 + if (label == 0) {
2.512 + IdMap<Graph, Edge> id_map(_graph);
2.513 + _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
2.514 + std::sort(edges.begin(), edges.end(), id_less);
2.515 + } else {
2.516 + label->sort(edges);
2.517 + }
2.518 +
2.519 + for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
2.520 + Edge e = edges[i];
2.521 + _writer_bits::writeToken(*_os, _node_index.
2.522 + find(_graph.u(e))->second);
2.523 + *_os << '\t';
2.524 + _writer_bits::writeToken(*_os, _node_index.
2.525 + find(_graph.v(e))->second);
2.526 + *_os << '\t';
2.527 + if (label == 0) {
2.528 + std::ostringstream os;
2.529 + os << _graph.id(e);
2.530 + _writer_bits::writeToken(*_os, os.str());
2.531 + *_os << '\t';
2.532 + _edge_index.insert(std::make_pair(e, os.str()));
2.533 + }
2.534 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
2.535 + it != _edge_maps.end(); ++it) {
2.536 + std::string value = it->second->get(e);
2.537 + _writer_bits::writeToken(*_os, value);
2.538 + if (it->first == "label") {
2.539 + _edge_index.insert(std::make_pair(e, value));
2.540 + }
2.541 + *_os << '\t';
2.542 + }
2.543 + *_os << std::endl;
2.544 + }
2.545 + }
2.546 +
2.547 + void writeAttributes() {
2.548 + if (_attributes.empty()) return;
2.549 + *_os << "@attributes";
2.550 + if (!_attributes_caption.empty()) {
2.551 + _writer_bits::writeToken(*_os << ' ', _attributes_caption);
2.552 + }
2.553 + *_os << std::endl;
2.554 + for (typename Attributes::iterator it = _attributes.begin();
2.555 + it != _attributes.end(); ++it) {
2.556 + _writer_bits::writeToken(*_os, it->first) << ' ';
2.557 + _writer_bits::writeToken(*_os, it->second->get());
2.558 + *_os << std::endl;
2.559 + }
2.560 + }
2.561 +
2.562 + public:
2.563 +
2.564 + /// \name Execution of the writer
2.565 + /// @{
2.566 +
2.567 + /// \brief Start the batch processing
2.568 + ///
2.569 + /// This function starts the batch processing
2.570 + void run() {
2.571 + if (!_skip_nodes) {
2.572 + writeNodes();
2.573 + }
2.574 + if (!_skip_edges) {
2.575 + writeEdges();
2.576 + }
2.577 + writeAttributes();
2.578 + }
2.579 +
2.580 + /// \brief Gives back the stream of the writer
2.581 + ///
2.582 + /// Gives back the stream of the writer
2.583 + std::ostream& ostream() {
2.584 + return *_os;
2.585 + }
2.586 +
2.587 + /// @}
2.588 + };
2.589 +
2.590 + /// \relates GraphWriter
2.591 + template <typename Graph>
2.592 + GraphWriter<Graph> graphWriter(std::ostream& os, Graph& graph) {
2.593 + GraphWriter<Graph> tmp(os, graph);
2.594 + return tmp;
2.595 + }
2.596 +
2.597 + /// \relates GraphWriter
2.598 + template <typename Graph>
2.599 + GraphWriter<Graph> graphWriter(const std::string& fn, Graph& graph) {
2.600 + GraphWriter<Graph> tmp(fn, graph);
2.601 + return tmp;
2.602 + }
2.603 +
2.604 + /// \relates GraphWriter
2.605 + template <typename Graph>
2.606 + GraphWriter<Graph> graphWriter(const char* fn, Graph& graph) {
2.607 + GraphWriter<Graph> tmp(fn, graph);
2.608 + return tmp;
2.609 + }
2.610 }
2.611
2.612 #endif