1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/lemon/lemon_reader.h Mon May 23 04:48:14 2005 +0000
1.3 @@ -0,0 +1,1977 @@
1.4 +/* -*- C++ -*-
1.5 + * lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
1.6 + *
1.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.9 + *
1.10 + * Permission to use, modify and distribute this software is granted
1.11 + * provided that this copyright notice appears in all copies. For
1.12 + * precise terms see the accompanying LICENSE file.
1.13 + *
1.14 + * This software is provided "AS IS" with no warranty of any kind,
1.15 + * express or implied, and with no claim as to its suitability for any
1.16 + * purpose.
1.17 + *
1.18 + */
1.19 +
1.20 +///\ingroup io_group
1.21 +///\file
1.22 +///\brief Lemon Format reader.
1.23 +
1.24 +
1.25 +#ifndef LEMON_LEMON_READER_H
1.26 +#define LEMON_LEMON_READER_H
1.27 +
1.28 +
1.29 +#include <iostream>
1.30 +#include <fstream>
1.31 +#include <string>
1.32 +#include <vector>
1.33 +#include <algorithm>
1.34 +#include <map>
1.35 +#include <memory>
1.36 +
1.37 +#include <lemon/error.h>
1.38 +#include <lemon/graph_utils.h>
1.39 +#include <lemon/utility.h>
1.40 +#include <lemon/bits/item_reader.h>
1.41 +
1.42 +
1.43 +namespace lemon {
1.44 +
1.45 + namespace _reader_bits {
1.46 +
1.47 + template <typename T>
1.48 + bool operator<(T, T) {
1.49 + throw DataFormatError("Id is not comparable");
1.50 + }
1.51 +
1.52 + template <typename T>
1.53 + struct Less {
1.54 + bool operator()(const T& p, const T& q) const {
1.55 + return p < q;
1.56 + }
1.57 + };
1.58 +
1.59 + template <typename M1, typename M2>
1.60 + class WriteComposeMap {
1.61 + public:
1.62 + typedef True NeedCopy;
1.63 +
1.64 + typedef typename M2::Key Key;
1.65 + typedef typename M1::Value Value;
1.66 +
1.67 + WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
1.68 + : m1(_m1), m2(_m2) {}
1.69 +
1.70 + void set(const Key& key, const Value& value) {
1.71 + m1.set(m2[key], value);
1.72 + }
1.73 +
1.74 + private:
1.75 +
1.76 + typename SmartReference<M1>::Type m1;
1.77 + typename SmartConstReference<M2>::Type m2;
1.78 +
1.79 + };
1.80 +
1.81 + template <typename M1, typename M2>
1.82 + WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
1.83 + return WriteComposeMap<M1, M2>(m1, m2);
1.84 + }
1.85 +
1.86 + template <typename M1, typename M2>
1.87 + WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
1.88 + return WriteComposeMap<M1, M2>(m1, m2);
1.89 + }
1.90 +
1.91 + }
1.92 +
1.93 + /// \ingroup io_group
1.94 + /// \brief Lemon Format reader class.
1.95 + ///
1.96 + /// The Lemon Format contains several sections. We do not want to
1.97 + /// determine what sections are in a lemon file we give only a framework
1.98 + /// to read a section oriented format.
1.99 + ///
1.100 + /// In the Lemon Format each section starts with a line contains a \c \@
1.101 + /// character on the first not white space position. This line is the
1.102 + /// header line of the section. Each next lines belong to this section
1.103 + /// while it does not starts with \c \@ character. This line can start a
1.104 + /// new section or if it can close the file with the \c \@end line.
1.105 + /// The file format ignore the empty and comment lines. The line is
1.106 + /// comment line if it starts with a \c # character.
1.107 + ///
1.108 + /// The framework provides an abstract LemonReader::SectionReader class
1.109 + /// what defines the interface of a SectionReader. The SectionReader
1.110 + /// has the \c header() member function what get a header line string and
1.111 + /// decides if it want to process the next section. Several SectionReaders
1.112 + /// can be attached to an LemonReader and the first attached what can
1.113 + /// process the section will be used. Its \c read() member will called
1.114 + /// with a stream contains the section. From this stream the empty and
1.115 + /// comment lines are filtered out.
1.116 + ///
1.117 + /// \relates GraphReader
1.118 + /// \relates NodeSetReader
1.119 + /// \relates EdgeSetReader
1.120 + /// \relates NodesReader
1.121 + /// \relates EdgesReader
1.122 + /// \relates AttributeReader
1.123 + class LemonReader {
1.124 + private:
1.125 +
1.126 + class FilterStreamBuf : public std::streambuf {
1.127 + public:
1.128 +
1.129 + typedef std::streambuf Parent;
1.130 + typedef Parent::char_type char_type;
1.131 + FilterStreamBuf(std::istream& is, int& num)
1.132 + : _is(is), _base(0), _eptr(0),
1.133 + _num(num), skip_state(after_endl) {}
1.134 +
1.135 + protected:
1.136 +
1.137 + enum skip_state_type {
1.138 + no_skip,
1.139 + after_endl,
1.140 + comment_line
1.141 + };
1.142 +
1.143 + char_type small_buf[1];
1.144 +
1.145 +
1.146 + std::istream& _is;
1.147 +
1.148 + char_type* _base;
1.149 + char_type* _eptr;
1.150 +
1.151 + int& _num;
1.152 +
1.153 + skip_state_type skip_state;
1.154 +
1.155 +
1.156 + char_type* base() { return _base; }
1.157 +
1.158 + char_type* eptr() { return _eptr; }
1.159 +
1.160 + int blen() { return _eptr - _base; }
1.161 +
1.162 + void setb(char_type* buf, int len) {
1.163 + _base = buf;
1.164 + _eptr = buf + len;
1.165 + }
1.166 +
1.167 + virtual std::streambuf* setbuf(char *buf, int len) {
1.168 + if (base()) return 0;
1.169 + if (buf != 0 && len >= (int)sizeof(small_buf)) {
1.170 + setb(buf, len);
1.171 + } else {
1.172 + setb(small_buf, sizeof(small_buf));
1.173 + }
1.174 + setg(0, 0, 0);
1.175 + return this;
1.176 + }
1.177 +
1.178 + bool put_char(char c) {
1.179 + switch (skip_state) {
1.180 + case no_skip:
1.181 + switch (c) {
1.182 + case '\n':
1.183 + skip_state = after_endl;
1.184 + return true;
1.185 + default:
1.186 + return true;
1.187 + }
1.188 + case after_endl:
1.189 + switch (c) {
1.190 + case '@':
1.191 + return false;
1.192 + case '\n':
1.193 + return false;
1.194 + case '#':
1.195 + skip_state = comment_line;
1.196 + return false;
1.197 + default:
1.198 + if (!isspace(c)) {
1.199 + skip_state = no_skip;
1.200 + return true;
1.201 + } else {
1.202 + return false;
1.203 + }
1.204 + }
1.205 + break;
1.206 + case comment_line:
1.207 + switch (c) {
1.208 + case '\n':
1.209 + skip_state = after_endl;
1.210 + return false;
1.211 + default:
1.212 + return false;
1.213 + }
1.214 + }
1.215 + return false;
1.216 + }
1.217 +
1.218 + virtual int underflow() {
1.219 + char c;
1.220 + if (_is.read(&c, 1)) {
1.221 + _is.putback(c);
1.222 + if (c == '@') {
1.223 + return EOF;
1.224 + }
1.225 + } else {
1.226 + return EOF;
1.227 + }
1.228 + char_type *ptr;
1.229 + for (ptr = base(); ptr != eptr(); ++ptr) {
1.230 + if (_is.read(&c, 1)) {
1.231 + if (c == '\n') ++_num;
1.232 + if (put_char(c)) {
1.233 + *ptr = c;
1.234 + } else {
1.235 + if (skip_state == after_endl && c == '@') {
1.236 + _is.putback('@');
1.237 + break;
1.238 + }
1.239 + --ptr;
1.240 + }
1.241 + } else {
1.242 + break;
1.243 + }
1.244 + }
1.245 + setg(base(), base(), ptr);
1.246 + return *base();
1.247 + }
1.248 +
1.249 + virtual int sync() {
1.250 + return EOF;
1.251 + }
1.252 + };
1.253 +
1.254 + public:
1.255 +
1.256 + /// \brief Abstract base class for reading a section.
1.257 + ///
1.258 + /// This class has an \c header() member function what get a
1.259 + /// header line string and decides if it want to process the next
1.260 + /// section. Several SectionReaders can be attached to an LemonReader
1.261 + /// and the first attached what can process the section will be used.
1.262 + /// Its \c read() member will called with a stream contains the section.
1.263 + /// From this stream the empty lines and comments are filtered out.
1.264 + class SectionReader {
1.265 + friend class LemonReader;
1.266 + protected:
1.267 + /// \brief Constructor for SectionReader.
1.268 + ///
1.269 + /// Constructor for SectionReader. It attach this reader to
1.270 + /// the given LemonReader.
1.271 + SectionReader(LemonReader& reader) {
1.272 + reader.attach(*this);
1.273 + }
1.274 +
1.275 + /// \brief Gives back true when the SectionReader can process
1.276 + /// the section with the given header line.
1.277 + ///
1.278 + /// It gives back true when the SectionReader can process
1.279 + /// the section with the given header line.
1.280 + virtual bool header(const std::string& line) = 0;
1.281 +
1.282 + /// \brief Reader function of the section.
1.283 + ///
1.284 + /// It reads the content of the section.
1.285 + virtual void read(std::istream& is) = 0;
1.286 + };
1.287 +
1.288 + /// \brief Constructor for LemonReader.
1.289 + ///
1.290 + /// Constructor for LemonReader which reads from the given stream.
1.291 + LemonReader(std::istream& _is)
1.292 + : is(&_is), own_is(false) {}
1.293 +
1.294 + /// \brief Constructor for LemonReader.
1.295 + ///
1.296 + /// Constructor for LemonReader which reads from the given file.
1.297 + LemonReader(const std::string& filename)
1.298 + : is(0), own_is(true) {
1.299 + is = new std::ifstream(filename.c_str());
1.300 + }
1.301 +
1.302 + /// \brief Desctructor for LemonReader.
1.303 + ///
1.304 + /// Desctructor for LemonReader.
1.305 + ~LemonReader() {
1.306 + if (own_is) {
1.307 + delete is;
1.308 + }
1.309 + }
1.310 +
1.311 + private:
1.312 + LemonReader(const LemonReader&);
1.313 + void operator=(const LemonReader&);
1.314 +
1.315 + void attach(SectionReader& reader) {
1.316 + readers.push_back(&reader);
1.317 + }
1.318 +
1.319 + public:
1.320 + /// \brief Executes the LemonReader.
1.321 + ///
1.322 + /// It executes the LemonReader.
1.323 + void run() {
1.324 + int line_num = 0;
1.325 + std::string line;
1.326 + try {
1.327 + while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
1.328 + SectionReaders::iterator it;
1.329 + for (it = readers.begin(); it != readers.end(); ++it) {
1.330 + if ((*it)->header(line)) {
1.331 + char buf[2048];
1.332 + FilterStreamBuf buffer(*is, line_num);
1.333 + buffer.pubsetbuf(buf, sizeof(buf));
1.334 + std::istream is(&buffer);
1.335 + (*it)->read(is);
1.336 + break;
1.337 + }
1.338 + }
1.339 + }
1.340 + } catch (DataFormatError& error) {
1.341 + error.line(line_num);
1.342 + throw error;
1.343 + }
1.344 + }
1.345 +
1.346 +
1.347 + private:
1.348 +
1.349 + std::istream* is;
1.350 + bool own_is;
1.351 +
1.352 + typedef std::vector<SectionReader*> SectionReaders;
1.353 + SectionReaders readers;
1.354 +
1.355 + };
1.356 +
1.357 + /// \brief Helper class for implementing the common SectionReaders.
1.358 + ///
1.359 + /// Helper class for implementing the common SectionReaders.
1.360 + class CommonSectionReaderBase : public LemonReader::SectionReader {
1.361 + typedef LemonReader::SectionReader Parent;
1.362 + protected:
1.363 +
1.364 + /// \brief Constructor for CommonSectionReaderBase.
1.365 + ///
1.366 + /// Constructor for CommonSectionReaderBase. It attach this reader to
1.367 + /// the given LemonReader.
1.368 + CommonSectionReaderBase(LemonReader& _reader)
1.369 + : Parent(_reader) {}
1.370 +
1.371 + template <typename _Item>
1.372 + class ReaderBase;
1.373 +
1.374 + template <typename _Item>
1.375 + class InverterBase : public ReaderBase<_Item> {
1.376 + public:
1.377 + typedef _Item Item;
1.378 + virtual void read(std::istream&, const Item&) = 0;
1.379 + virtual Item read(std::istream&) const = 0;
1.380 +
1.381 + virtual InverterBase<_Item>* getInverter() {
1.382 + return this;
1.383 + }
1.384 + };
1.385 +
1.386 + template <typename _Item, typename _Map, typename _Reader>
1.387 + class MapReaderInverter : public InverterBase<_Item> {
1.388 + public:
1.389 + typedef _Item Item;
1.390 + typedef _Reader Reader;
1.391 + typedef typename Reader::Value Value;
1.392 + typedef _Map Map;
1.393 + typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
1.394 +
1.395 + typename SmartReference<Map>::Type map;
1.396 + Reader reader;
1.397 + Inverse inverse;
1.398 +
1.399 + MapReaderInverter(typename SmartParameter<Map>::Type _map,
1.400 + const Reader& _reader)
1.401 + : map(_map), reader(_reader) {}
1.402 +
1.403 + virtual ~MapReaderInverter() {}
1.404 +
1.405 + virtual void read(std::istream& is, const Item& item) {
1.406 + Value value;
1.407 + reader.read(is, value);
1.408 + map.set(item, value);
1.409 + typename Inverse::iterator it = inverse.find(value);
1.410 + if (it == inverse.end()) {
1.411 + inverse.insert(std::make_pair(value, item));
1.412 + } else {
1.413 + throw DataFormatError("Multiple ID occurence");
1.414 + }
1.415 + }
1.416 +
1.417 + virtual Item read(std::istream& is) const {
1.418 + Value value;
1.419 + reader.read(is, value);
1.420 + typename Inverse::const_iterator it = inverse.find(value);
1.421 + if (it != inverse.end()) {
1.422 + return it->second;
1.423 + } else {
1.424 + throw DataFormatError("Invalid ID error");
1.425 + }
1.426 + }
1.427 + };
1.428 +
1.429 + template <typename _Item, typename _Reader>
1.430 + class SkipReaderInverter : public InverterBase<_Item> {
1.431 + public:
1.432 + typedef _Item Item;
1.433 + typedef _Reader Reader;
1.434 + typedef typename Reader::Value Value;
1.435 + typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
1.436 +
1.437 + Reader reader;
1.438 +
1.439 + SkipReaderInverter(const Reader& _reader)
1.440 + : reader(_reader) {}
1.441 +
1.442 + virtual ~SkipReaderInverter() {}
1.443 +
1.444 + virtual void read(std::istream& is, const Item& item) {
1.445 + Value value;
1.446 + reader.read(is, value);
1.447 + typename Inverse::iterator it = inverse.find(value);
1.448 + if (it == inverse.end()) {
1.449 + inverse.insert(std::make_pair(value, item));
1.450 + } else {
1.451 + throw DataFormatError("Multiple ID occurence error");
1.452 + }
1.453 + }
1.454 +
1.455 + virtual Item read(std::istream& is) const {
1.456 + Value value;
1.457 + reader.read(is, value);
1.458 + typename Inverse::const_iterator it = inverse.find(value);
1.459 + if (it != inverse.end()) {
1.460 + return it->second;
1.461 + } else {
1.462 + throw DataFormatError("Invalid ID error");
1.463 + }
1.464 + }
1.465 +
1.466 + private:
1.467 + Inverse inverse;
1.468 + };
1.469 +
1.470 + template <typename _Item>
1.471 + class ReaderBase {
1.472 + public:
1.473 + typedef _Item Item;
1.474 +
1.475 + virtual ~ReaderBase() {}
1.476 +
1.477 + virtual void read(std::istream& is, const Item& item) = 0;
1.478 + virtual InverterBase<_Item>* getInverter() = 0;
1.479 + };
1.480 +
1.481 + template <typename _Item, typename _Map, typename _Reader>
1.482 + class MapReader : public ReaderBase<_Item> {
1.483 + public:
1.484 + typedef _Map Map;
1.485 + typedef _Reader Reader;
1.486 + typedef typename Reader::Value Value;
1.487 + typedef _Item Item;
1.488 +
1.489 + typename SmartReference<Map>::Type map;
1.490 + Reader reader;
1.491 +
1.492 + MapReader(typename SmartParameter<Map>::Type _map,
1.493 + const Reader& _reader)
1.494 + : map(_map), reader(_reader) {}
1.495 +
1.496 + virtual ~MapReader() {}
1.497 +
1.498 + virtual void read(std::istream& is, const Item& item) {
1.499 + Value value;
1.500 + reader.read(is, value);
1.501 + map.set(item, value);
1.502 + }
1.503 +
1.504 + virtual InverterBase<_Item>* getInverter() {
1.505 + return new MapReaderInverter<Item, Map, Reader>(map, reader);
1.506 + }
1.507 + };
1.508 +
1.509 +
1.510 + template <typename _Item, typename _Reader>
1.511 + class SkipReader : public ReaderBase<_Item> {
1.512 + public:
1.513 + typedef _Reader Reader;
1.514 + typedef typename Reader::Value Value;
1.515 + typedef _Item Item;
1.516 +
1.517 + Reader reader;
1.518 + SkipReader(const Reader& _reader) : reader(_reader) {}
1.519 +
1.520 + virtual ~SkipReader() {}
1.521 +
1.522 + virtual void read(std::istream& is, const Item&) {
1.523 + Value value;
1.524 + reader.read(is, value);
1.525 + }
1.526 +
1.527 + virtual InverterBase<Item>* getInverter() {
1.528 + return new SkipReaderInverter<Item, Reader>(reader);
1.529 + }
1.530 + };
1.531 +
1.532 + template <typename _Item>
1.533 + class IdReaderBase {
1.534 + public:
1.535 + typedef _Item Item;
1.536 + virtual Item read(std::istream& is) const = 0;
1.537 + };
1.538 +
1.539 + template <typename _Item, typename _BoxedIdReader>
1.540 + class IdReader : public IdReaderBase<_Item> {
1.541 + public:
1.542 + typedef _Item Item;
1.543 + typedef _BoxedIdReader BoxedIdReader;
1.544 +
1.545 + const BoxedIdReader& boxedIdReader;
1.546 +
1.547 + IdReader(const BoxedIdReader& _boxedIdReader)
1.548 + : boxedIdReader(_boxedIdReader) {}
1.549 +
1.550 + virtual Item read(std::istream& is) const {
1.551 + return boxedIdReader.readId(is, Item());
1.552 + }
1.553 + };
1.554 +
1.555 + class ValueReaderBase {
1.556 + public:
1.557 + virtual void read(std::istream&) {};
1.558 + };
1.559 +
1.560 + template <typename _Value, typename _Reader>
1.561 + class ValueReader : public ValueReaderBase {
1.562 + public:
1.563 + typedef _Value Value;
1.564 + typedef _Reader Reader;
1.565 +
1.566 + ValueReader(Value& _value, const Reader& _reader)
1.567 + : value(_value), reader(_reader) {}
1.568 +
1.569 + virtual void read(std::istream& is) {
1.570 + reader.read(is, value);
1.571 + }
1.572 + private:
1.573 + Value& value;
1.574 + Reader reader;
1.575 + };
1.576 +
1.577 + };
1.578 +
1.579 + /// \ingroup io_group
1.580 + /// \brief SectionReader for reading a graph's nodeset.
1.581 + ///
1.582 + /// The lemon format can store multiple graph nodesets with several maps.
1.583 + /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
1.584 + /// \c nodeset_id may be empty.
1.585 + ///
1.586 + /// The first line of the section contains the names of the maps separated
1.587 + /// with white spaces. Each next lines describes a node in the nodeset, and
1.588 + /// contains the mapped values for each map.
1.589 + ///
1.590 + /// If the nodeset contains an \c "id" named map then it will be regarded
1.591 + /// as id map. This map should contain only unique values and when the
1.592 + /// \c readId() member will read a value from the given stream it will
1.593 + /// give back that node which is mapped to this value.
1.594 + ///
1.595 + /// \relates LemonReader
1.596 + template <typename _Graph, typename _Traits = DefaultReaderTraits>
1.597 + class NodeSetReader : public CommonSectionReaderBase {
1.598 + typedef CommonSectionReaderBase Parent;
1.599 + public:
1.600 +
1.601 + typedef _Graph Graph;
1.602 + typedef _Traits Traits;
1.603 + typedef typename Graph::Node Node;
1.604 + typedef typename Traits::Skipper DefaultSkipper;
1.605 +
1.606 + /// \brief Constructor.
1.607 + ///
1.608 + /// Constructor for NodeSetReader. It creates the NodeSetReader and
1.609 + /// attach it into the given LemonReader. The nodeset reader will
1.610 + /// add the readed nodes to the given Graph. The reader will read
1.611 + /// the section when the \c section_id and the \c _id are the same.
1.612 + NodeSetReader(LemonReader& _reader,
1.613 + typename SmartParameter<Graph>::Type _graph,
1.614 + const std::string& _id = std::string(),
1.615 + const DefaultSkipper& _skipper = DefaultSkipper())
1.616 + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
1.617 +
1.618 +
1.619 + /// \brief Destructor.
1.620 + ///
1.621 + /// Destructor for NodeSetReader.
1.622 + virtual ~NodeSetReader() {
1.623 + for (typename MapReaders::iterator it = readers.begin();
1.624 + it != readers.end(); ++it) {
1.625 + delete it->second;
1.626 + }
1.627 + }
1.628 +
1.629 + private:
1.630 + NodeSetReader(const NodeSetReader&);
1.631 + void operator=(const NodeSetReader&);
1.632 +
1.633 + public:
1.634 +
1.635 + /// \brief Add a new node map reader command for the reader.
1.636 + ///
1.637 + /// Add a new node map reader command for the reader.
1.638 + template <typename Map>
1.639 + NodeSetReader& readNodeMap(std::string name, Map& map) {
1.640 + return _readMap<
1.641 + typename Traits::template Reader<typename Map::Value>, Map,
1.642 + typename SmartParameter<Map>::Type>(name, map);
1.643 + }
1.644 +
1.645 + template <typename Map>
1.646 + NodeSetReader& readNodeMap(std::string name, const Map& map) {
1.647 + return _readMap<
1.648 + typename Traits::template Reader<typename Map::Value>, Map,
1.649 + typename SmartParameter<Map>::Type>(name, map);
1.650 + }
1.651 +
1.652 + /// \brief Add a new node map reader command for the reader.
1.653 + ///
1.654 + /// Add a new node map reader command for the reader.
1.655 + template <typename Reader, typename Map>
1.656 + NodeSetReader& readNodeMap(std::string name, Map& map,
1.657 + const Reader& reader = Reader()) {
1.658 + return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1.659 + (name, map, reader);
1.660 + }
1.661 +
1.662 + template <typename Reader, typename Map>
1.663 + NodeSetReader& readNodeMap(std::string name, const Map& map,
1.664 + const Reader& reader = Reader()) {
1.665 + return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1.666 + (name, map, reader);
1.667 + }
1.668 +
1.669 + private:
1.670 +
1.671 + template <typename Reader, typename Map, typename MapParameter>
1.672 + NodeSetReader& _readMap(std::string name, MapParameter map,
1.673 + const Reader& reader = Reader()) {
1.674 + if (readers.find(name) != readers.end()) {
1.675 + ErrorMessage msg;
1.676 + msg << "Multiple read rule for node map: " << name;
1.677 + throw IOParameterError(msg.message());
1.678 + }
1.679 + readers.insert(
1.680 + make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
1.681 + return *this;
1.682 + }
1.683 +
1.684 + public:
1.685 +
1.686 + /// \brief Add a new node map skipper command for the reader.
1.687 + ///
1.688 + /// Add a new node map skipper command for the reader.
1.689 + template <typename Reader>
1.690 + NodeSetReader& skipNodeMap(std::string name,
1.691 + const Reader& reader = Reader()) {
1.692 + if (readers.find(name) != readers.end()) {
1.693 + ErrorMessage msg;
1.694 + msg << "Multiple read rule for node map: " << name;
1.695 + throw IOParameterError(msg.message());
1.696 + }
1.697 + readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
1.698 + return *this;
1.699 + }
1.700 +
1.701 + protected:
1.702 +
1.703 + /// \brief Gives back true when the SectionReader can process
1.704 + /// the section with the given header line.
1.705 + ///
1.706 + /// It gives back true when the header line starts with \c \@nodeset,
1.707 + /// and the header line's id and the nodeset's id are the same.
1.708 + virtual bool header(const std::string& line) {
1.709 + std::istringstream ls(line);
1.710 + std::string command;
1.711 + std::string name;
1.712 + ls >> command >> name;
1.713 + return command == "@nodeset" && name == id;
1.714 + }
1.715 +
1.716 + /// \brief Reader function of the section.
1.717 + ///
1.718 + /// It reads the content of the section.
1.719 + virtual void read(std::istream& is) {
1.720 + std::vector<ReaderBase<Node>* > index;
1.721 + std::string line;
1.722 +
1.723 + getline(is, line);
1.724 + std::istringstream ls(line);
1.725 + while (ls >> id) {
1.726 + typename MapReaders::iterator it = readers.find(id);
1.727 + if (it != readers.end()) {
1.728 + index.push_back(it->second);
1.729 + } else {
1.730 + index.push_back(&skipper);
1.731 + }
1.732 + if (id == "id" && inverter.get() == 0) {
1.733 + inverter.reset(index.back()->getInverter());
1.734 + index.back() = inverter.get();
1.735 + }
1.736 + }
1.737 + while (getline(is, line)) {
1.738 + Node node = graph.addNode();
1.739 + std::istringstream ls(line);
1.740 + for (int i = 0; i < (int)index.size(); ++i) {
1.741 + index[i]->read(ls, node);
1.742 + }
1.743 + }
1.744 + }
1.745 +
1.746 + public:
1.747 +
1.748 + /// \brief Returns true if the nodeset can give back the node by its id.
1.749 + ///
1.750 + /// Returns true if the nodeset can give back the node by its id.
1.751 + /// It is possible only if an "id" named map was read.
1.752 + bool isIdReader() const {
1.753 + return inverter.get() != 0;
1.754 + }
1.755 +
1.756 + /// \brief Gives back the node by its id.
1.757 + ///
1.758 + /// It reads an id from the stream and gives back which node belongs to
1.759 + /// it. It is possible only if there was read an "id" named map.
1.760 + Node readId(std::istream& is, Node = Node()) const {
1.761 + return inverter->read(is);
1.762 + }
1.763 +
1.764 + private:
1.765 +
1.766 + typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
1.767 + MapReaders readers;
1.768 +
1.769 + typename SmartReference<Graph>::Type graph;
1.770 + std::string id;
1.771 + SkipReader<Node, DefaultSkipper> skipper;
1.772 +
1.773 + std::auto_ptr<InverterBase<Node> > inverter;
1.774 + };
1.775 +
1.776 + /// \ingroup io_group
1.777 + /// \brief SectionReader for reading a graph's edgeset.
1.778 + ///
1.779 + /// The lemon format can store multiple graph edgesets with several maps.
1.780 + /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
1.781 + /// \c edgeset_id may be empty.
1.782 + ///
1.783 + /// The first line of the section contains the names of the maps separated
1.784 + /// with white spaces. Each next lines describes an edge in the edgeset. The
1.785 + /// line contains the source and the target nodes' id and the mapped
1.786 + /// values for each map.
1.787 + ///
1.788 + /// If the edgeset contains an \c "id" named map then it will be regarded
1.789 + /// as id map. This map should contain only unique values and when the
1.790 + /// \c readId() member will read a value from the given stream it will
1.791 + /// give back that edge which is mapped to this value.
1.792 + ///
1.793 + /// The edgeset reader needs a node id reader to identify which nodes
1.794 + /// have to be connected. If a NodeSetReader reads an "id" named map,
1.795 + /// it will be able to resolve the nodes by ids.
1.796 + ///
1.797 + /// \relates LemonReader
1.798 + template <typename _Graph, typename _Traits = DefaultReaderTraits>
1.799 + class EdgeSetReader : public CommonSectionReaderBase {
1.800 + typedef CommonSectionReaderBase Parent;
1.801 + public:
1.802 +
1.803 + typedef _Graph Graph;
1.804 + typedef _Traits Traits;
1.805 + typedef typename Graph::Node Node;
1.806 + typedef typename Graph::Edge Edge;
1.807 + typedef typename Traits::Skipper DefaultSkipper;
1.808 +
1.809 + /// \brief Constructor.
1.810 + ///
1.811 + /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1.812 + /// attach it into the given LemonReader. The edgeset reader will
1.813 + /// add the readed edges to the given Graph. It will use the given
1.814 + /// node id reader to read the source and target nodes of the edges.
1.815 + /// The reader will read the section only if the \c _id and the
1.816 + /// \c edgset_id are the same.
1.817 + template <typename NodeIdReader>
1.818 + EdgeSetReader(LemonReader& _reader,
1.819 + typename SmartParameter<Graph>::Type _graph,
1.820 + const NodeIdReader& _nodeIdReader,
1.821 + const std::string& _id = std::string(),
1.822 + const DefaultSkipper& _skipper = DefaultSkipper())
1.823 + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
1.824 + nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {}
1.825 +
1.826 + /// \brief Destructor.
1.827 + ///
1.828 + /// Destructor for EdgeSetReader.
1.829 + virtual ~EdgeSetReader() {
1.830 + for (typename MapReaders::iterator it = readers.begin();
1.831 + it != readers.end(); ++it) {
1.832 + delete it->second;
1.833 + }
1.834 + }
1.835 +
1.836 + private:
1.837 + EdgeSetReader(const EdgeSetReader&);
1.838 + void operator=(const EdgeSetReader&);
1.839 +
1.840 + public:
1.841 +
1.842 + /// \brief Add a new edge map reader command for the reader.
1.843 + ///
1.844 + /// Add a new edge map reader command for the reader.
1.845 + template <typename Map>
1.846 + EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1.847 + return _readMap<
1.848 + typename Traits::template Reader<typename Map::Value>, Map,
1.849 + typename SmartParameter<Map>::Type>(name, map);
1.850 + }
1.851 +
1.852 + template <typename Map>
1.853 + EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1.854 + return _readMap<
1.855 + typename Traits::template Reader<typename Map::Value>, Map,
1.856 + typename SmartParameter<Map>::Type>(name, map);
1.857 + }
1.858 +
1.859 + /// \brief Add a new edge map reader command for the reader.
1.860 + ///
1.861 + /// Add a new edge map reader command for the reader.
1.862 + template <typename Reader, typename Map>
1.863 + EdgeSetReader& readEdgeMap(std::string name, Map& map,
1.864 + const Reader& reader = Reader()) {
1.865 + return _readMap<Reader, Map,
1.866 + typename SmartParameter<Map>::Type>(name, map, reader);
1.867 + }
1.868 +
1.869 + template <typename Reader, typename Map>
1.870 + EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1.871 + const Reader& reader = Reader()) {
1.872 + return _readMap<Reader, Map,
1.873 + typename SmartParameter<Map>::Type>(name, map, reader);
1.874 + }
1.875 +
1.876 + private:
1.877 +
1.878 + template <typename Reader, typename Map, typename MapParameter>
1.879 + EdgeSetReader& _readMap(std::string name, MapParameter map,
1.880 + const Reader& reader = Reader()) {
1.881 + if (readers.find(name) != readers.end()) {
1.882 + ErrorMessage msg;
1.883 + msg << "Multiple read rule for edge map: " << name;
1.884 + throw IOParameterError(msg.message());
1.885 + }
1.886 + readers.insert(
1.887 + make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
1.888 + return *this;
1.889 + }
1.890 +
1.891 + public:
1.892 +
1.893 + /// \brief Add a new edge map skipper command for the reader.
1.894 + ///
1.895 + /// Add a new edge map skipper command for the reader.
1.896 + template <typename Reader>
1.897 + EdgeSetReader& skipEdgeMap(std::string name,
1.898 + const Reader& reader = Reader()) {
1.899 + if (readers.find(name) != readers.end()) {
1.900 + ErrorMessage msg;
1.901 + msg << "Multiple read rule for edge map: " << name;
1.902 + throw IOParameterError(msg.message());
1.903 + }
1.904 + readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
1.905 + return *this;
1.906 + }
1.907 +
1.908 + protected:
1.909 +
1.910 + /// \brief Gives back true when the SectionReader can process
1.911 + /// the section with the given header line.
1.912 + ///
1.913 + /// It gives back true when the header line starts with \c \@edgeset,
1.914 + /// and the header line's id and the edgeset's id are the same.
1.915 + virtual bool header(const std::string& line) {
1.916 + std::istringstream ls(line);
1.917 + std::string command;
1.918 + std::string name;
1.919 + ls >> command >> name;
1.920 + return command == "@edgeset" && name == id;
1.921 + }
1.922 +
1.923 + /// \brief Reader function of the section.
1.924 + ///
1.925 + /// It reads the content of the section.
1.926 + virtual void read(std::istream& is) {
1.927 + std::vector<ReaderBase<Edge>* > index;
1.928 + std::string line;
1.929 +
1.930 + getline(is, line);
1.931 + std::istringstream ls(line);
1.932 + while (ls >> id) {
1.933 + typename MapReaders::iterator it = readers.find(id);
1.934 + if (it != readers.end()) {
1.935 + index.push_back(it->second);
1.936 + } else {
1.937 + index.push_back(&skipper);
1.938 + }
1.939 + if (id == "id" && inverter.get() == 0) {
1.940 + inverter.reset(index.back()->getInverter());
1.941 + index.back() = inverter.get();
1.942 + }
1.943 + }
1.944 + while (getline(is, line)) {
1.945 + std::istringstream ls(line);
1.946 + Node from = nodeIdReader->read(ls);
1.947 + Node to = nodeIdReader->read(ls);
1.948 + Edge edge = graph.addEdge(from, to);
1.949 + for (int i = 0; i < (int)index.size(); ++i) {
1.950 + index[i]->read(ls, edge);
1.951 + }
1.952 + }
1.953 + }
1.954 +
1.955 + public:
1.956 +
1.957 + /// \brief Returns true if the edgeset can give back the edge by its id.
1.958 + ///
1.959 + /// Returns true if the edgeset can give back the edge by its id.
1.960 + /// It is possible only if an "id" named map was read.
1.961 + bool isIdReader() const {
1.962 + return inverter.get() != 0;
1.963 + }
1.964 +
1.965 + /// \brief Gives back the edge by its id.
1.966 + ///
1.967 + /// It reads an id from the stream and gives back which edge belongs to
1.968 + /// it. It is possible only if there was read an "id" named map.
1.969 + Edge readId(std::istream& is, Edge = Edge()) const {
1.970 + return inverter->read(is);
1.971 + }
1.972 +
1.973 + private:
1.974 +
1.975 + typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
1.976 + MapReaders readers;
1.977 +
1.978 + typename SmartReference<Graph>::Type graph;
1.979 + std::string id;
1.980 + SkipReader<Edge, DefaultSkipper> skipper;
1.981 +
1.982 + std::auto_ptr<InverterBase<Edge> > inverter;
1.983 + std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1.984 + };
1.985 +
1.986 + /// \ingroup io_group
1.987 + /// \brief SectionReader for reading a undirected graph's edgeset.
1.988 + ///
1.989 + /// The lemon format can store multiple undirected edgesets with several
1.990 + /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1.991 + /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1.992 + ///
1.993 + /// The first line of the section contains the names of the maps separated
1.994 + /// with white spaces. Each next lines describes an edge in the edgeset. The
1.995 + /// line contains the connected nodes' id and the mapped values for each map.
1.996 + ///
1.997 + /// The section can handle the directed as a syntactical sugar. Two
1.998 + /// undirected edge map describes one directed edge map. This two maps
1.999 + /// are the forward map and the backward map and the names of this map
1.1000 + /// is near the same just with a prefix \c '+' or \c '-' character
1.1001 + /// difference.
1.1002 + ///
1.1003 + /// If the edgeset contains an \c "id" named map then it will be regarded
1.1004 + /// as id map. This map should contain only unique values and when the
1.1005 + /// \c readId() member will read a value from the given stream it will
1.1006 + /// give back that undiricted edge which is mapped to this value.
1.1007 + ///
1.1008 + /// The undirected edgeset reader needs a node id reader to identify which
1.1009 + /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1.1010 + /// it will be able to resolve the nodes by ids.
1.1011 + ///
1.1012 + /// \relates LemonReader
1.1013 + template <typename _Graph, typename _Traits = DefaultReaderTraits>
1.1014 + class UndirEdgeSetReader : public CommonSectionReaderBase {
1.1015 + typedef CommonSectionReaderBase Parent;
1.1016 + public:
1.1017 +
1.1018 + typedef _Graph Graph;
1.1019 + typedef _Traits Traits;
1.1020 + typedef typename Graph::Node Node;
1.1021 + typedef typename Graph::Edge Edge;
1.1022 + typedef typename Graph::UndirEdge UndirEdge;
1.1023 + typedef typename Traits::Skipper DefaultSkipper;
1.1024 +
1.1025 + /// \brief Constructor.
1.1026 + ///
1.1027 + /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1.1028 + /// and attach it into the given LemonReader. The undirected edgeset
1.1029 + /// reader will add the readed undirected edges to the given Graph. It
1.1030 + /// will use the given node id reader to read the source and target
1.1031 + /// nodes of the edges. The reader will read the section only if the
1.1032 + /// \c _id and the \c undiredgset_id are the same.
1.1033 + template <typename NodeIdReader>
1.1034 + UndirEdgeSetReader(LemonReader& _reader,
1.1035 + typename SmartParameter<Graph>::Type _graph,
1.1036 + const NodeIdReader& _nodeIdReader,
1.1037 + const std::string& _id = std::string(),
1.1038 + const DefaultSkipper& _skipper = DefaultSkipper())
1.1039 + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
1.1040 + nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {}
1.1041 +
1.1042 + /// \brief Destructor.
1.1043 + ///
1.1044 + /// Destructor for UndirEdgeSetReader.
1.1045 + virtual ~UndirEdgeSetReader() {
1.1046 + for (typename MapReaders::iterator it = readers.begin();
1.1047 + it != readers.end(); ++it) {
1.1048 + delete it->second;
1.1049 + }
1.1050 + }
1.1051 +
1.1052 + private:
1.1053 + UndirEdgeSetReader(const UndirEdgeSetReader&);
1.1054 + void operator=(const UndirEdgeSetReader&);
1.1055 +
1.1056 + public:
1.1057 +
1.1058 + /// \brief Add a new undirected edge map reader command for the reader.
1.1059 + ///
1.1060 + /// Add a new edge undirected map reader command for the reader.
1.1061 + template <typename Map>
1.1062 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1.1063 + return _readMap<
1.1064 + typename Traits::template Reader<typename Map::Value>, Map,
1.1065 + typename SmartParameter<Map>::Type>(name, map);
1.1066 + }
1.1067 +
1.1068 + template <typename Map>
1.1069 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1.1070 + return _readMap<
1.1071 + typename Traits::template Reader<typename Map::Value>, Map,
1.1072 + typename SmartParameter<Map>::Type>(name, map);
1.1073 + }
1.1074 +
1.1075 + /// \brief Add a new undirected edge map reader command for the reader.
1.1076 + ///
1.1077 + /// Add a new edge undirected map reader command for the reader.
1.1078 + template <typename Reader, typename Map>
1.1079 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1.1080 + const Reader& reader = Reader()) {
1.1081 + return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1.1082 + (name, map, reader);
1.1083 + }
1.1084 +
1.1085 + template <typename Reader, typename Map>
1.1086 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1.1087 + const Reader& reader = Reader()) {
1.1088 + return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
1.1089 + (name, map, reader);
1.1090 + }
1.1091 +
1.1092 + private:
1.1093 +
1.1094 + template <typename Reader, typename Map, typename MapParameter>
1.1095 + UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1.1096 + const Reader& reader = Reader()) {
1.1097 + if (readers.find(name) != readers.end()) {
1.1098 + ErrorMessage msg;
1.1099 + msg << "Multiple read rule for edge map: " << name;
1.1100 + throw IOParameterError(msg.message());
1.1101 + }
1.1102 + readers.insert(
1.1103 + make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1.1104 + return *this;
1.1105 + }
1.1106 +
1.1107 + public:
1.1108 +
1.1109 + /// \brief Add a new undirected edge map skipper command for the reader.
1.1110 + ///
1.1111 + /// Add a new undirected edge map skipper command for the reader.
1.1112 + template <typename Reader>
1.1113 + UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1.1114 + const Reader& reader = Reader()) {
1.1115 + if (readers.find(name) != readers.end()) {
1.1116 + ErrorMessage msg;
1.1117 + msg << "Multiple read rule for node map: " << name;
1.1118 + throw IOParameterError(msg.message());
1.1119 + }
1.1120 + readers.insert(make_pair(name,
1.1121 + new SkipReader<UndirEdge, Reader>(reader)));
1.1122 + return *this;
1.1123 + }
1.1124 +
1.1125 + /// \brief Add a new directed edge map reader command for the reader.
1.1126 + ///
1.1127 + /// Add a new directed edge map reader command for the reader.
1.1128 + template <typename Map>
1.1129 + UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1.1130 + return _readDirMap<
1.1131 + typename Traits::template Reader<typename Map::Value>, Map,
1.1132 + typename SmartParameter<Map>::Type>(name, map);
1.1133 + }
1.1134 +
1.1135 + template <typename Map>
1.1136 + UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1.1137 + return _readDirMap<
1.1138 + typename Traits::template Reader<typename Map::Value>, Map,
1.1139 + typename SmartParameter<Map>::Type>(name, map);
1.1140 + }
1.1141 +
1.1142 + /// \brief Add a new directed edge map reader command for the reader.
1.1143 + ///
1.1144 + /// Add a new directed edge map reader command for the reader.
1.1145 + template <typename Reader, typename Map>
1.1146 + UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1.1147 + const Reader& reader = Reader()) {
1.1148 + return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1.1149 + (name, map, reader);
1.1150 + }
1.1151 +
1.1152 + template <typename Reader, typename Map>
1.1153 + UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1.1154 + const Reader& reader = Reader()) {
1.1155 + return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1.1156 + (name, map, reader);
1.1157 + }
1.1158 +
1.1159 + private:
1.1160 +
1.1161 + template <typename Reader, typename Map, typename MapParameter>
1.1162 + UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1.1163 + const Reader& reader = Reader()) {
1.1164 + readMap("+" + name,
1.1165 + _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
1.1166 + readMap("-" + name,
1.1167 + _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
1.1168 + return *this;
1.1169 + }
1.1170 +
1.1171 + public:
1.1172 +
1.1173 + /// \brief Add a new directed edge map skipper command for the reader.
1.1174 + ///
1.1175 + /// Add a new directed edge map skipper command for the reader.
1.1176 + template <typename Reader>
1.1177 + UndirEdgeSetReader& skipEdgeMap(std::string name,
1.1178 + const Reader& reader = Reader()) {
1.1179 + skipMap("+" + name, reader);
1.1180 + skipMap("-" + name, reader);
1.1181 + return *this;
1.1182 + }
1.1183 +
1.1184 + protected:
1.1185 +
1.1186 + /// \brief Gives back true when the SectionReader can process
1.1187 + /// the section with the given header line.
1.1188 + ///
1.1189 + /// It gives back true when the header line starts with \c \@undiredgeset,
1.1190 + /// and the header line's id and the edgeset's id are the same.
1.1191 + virtual bool header(const std::string& line) {
1.1192 + std::istringstream ls(line);
1.1193 + std::string command;
1.1194 + std::string name;
1.1195 + ls >> command >> name;
1.1196 + return command == "@undiredgeset" && name == id;
1.1197 + }
1.1198 +
1.1199 + /// \brief Reader function of the section.
1.1200 + ///
1.1201 + /// It reads the content of the section.
1.1202 + virtual void read(std::istream& is) {
1.1203 + std::vector<ReaderBase<UndirEdge>* > index;
1.1204 + std::string line;
1.1205 +
1.1206 + getline(is, line);
1.1207 + std::istringstream ls(line);
1.1208 + while (ls >> id) {
1.1209 + typename MapReaders::iterator it = readers.find(id);
1.1210 + if (it != readers.end()) {
1.1211 + index.push_back(it->second);
1.1212 + } else {
1.1213 + index.push_back(&skipper);
1.1214 + }
1.1215 + if (id == "id" && inverter.get() == 0) {
1.1216 + inverter.reset(index.back()->getInverter());
1.1217 + index.back() = inverter.get();
1.1218 + }
1.1219 + }
1.1220 + while (getline(is, line)) {
1.1221 + std::istringstream ls(line);
1.1222 + Node from = nodeIdReader->read(ls);
1.1223 + Node to = nodeIdReader->read(ls);
1.1224 + UndirEdge edge = graph.addEdge(from, to);
1.1225 + for (int i = 0; i < (int)index.size(); ++i) {
1.1226 + index[i]->read(ls, edge);
1.1227 + }
1.1228 + }
1.1229 + }
1.1230 +
1.1231 + public:
1.1232 +
1.1233 + /// \brief Returns true if the edgeset can give back the edge by its id.
1.1234 + ///
1.1235 + /// Returns true if the edgeset can give back the undirected edge by its
1.1236 + /// id. It is possible only if an "id" named map was read.
1.1237 + bool isIdReader() const {
1.1238 + return inverter.get() != 0;
1.1239 + }
1.1240 +
1.1241 + /// \brief Gives back the undirected edge by its id.
1.1242 + ///
1.1243 + /// It reads an id from the stream and gives back which undirected edge
1.1244 + /// belongs to it. It is possible only if there was read an "id" named map.
1.1245 + UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const {
1.1246 + return inverter->read(is);
1.1247 + }
1.1248 +
1.1249 + /// \brief Gives back the directed edge by its id.
1.1250 + ///
1.1251 + /// It reads an id from the stream and gives back which directed edge
1.1252 + /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1.1253 + /// and the undirected edge id. It is possible only if there was read
1.1254 + /// an "id" named map.
1.1255 + Edge readId(std::istream& is, Edge = Edge()) const {
1.1256 + char c;
1.1257 + is >> c;
1.1258 + UndirEdge undirEdge = inverter->read(is);
1.1259 + if (c == '+') {
1.1260 + return graph.edgeWithSource(undirEdge, graph.source(undirEdge));
1.1261 + } else if (c == '-') {
1.1262 + return graph.edgeWithSource(undirEdge, graph.target(undirEdge));
1.1263 + } else {
1.1264 + throw DataFormatError("Wrong id format for edge "
1.1265 + "in undirected edgeset");
1.1266 + }
1.1267 + }
1.1268 +
1.1269 + private:
1.1270 +
1.1271 + typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1.1272 + MapReaders readers;
1.1273 +
1.1274 + typename SmartReference<Graph>::Type graph;
1.1275 + std::string id;
1.1276 + SkipReader<UndirEdge, DefaultSkipper> skipper;
1.1277 +
1.1278 + std::auto_ptr<InverterBase<UndirEdge> > inverter;
1.1279 + std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1.1280 + };
1.1281 +
1.1282 + /// \ingroup io_group
1.1283 + /// \brief SectionReader for reading labeled nodes.
1.1284 + ///
1.1285 + /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1.1286 + /// \c nodes_id may be empty.
1.1287 + ///
1.1288 + /// Each line in the section contains the name of the node
1.1289 + /// and then the node id.
1.1290 + ///
1.1291 + /// \relates LemonReader
1.1292 + template <typename _Graph>
1.1293 + class NodeReader : public CommonSectionReaderBase {
1.1294 + typedef CommonSectionReaderBase Parent;
1.1295 + typedef _Graph Graph;
1.1296 + typedef typename Graph::Node Node;
1.1297 + public:
1.1298 +
1.1299 + /// \brief Constructor.
1.1300 + ///
1.1301 + /// Constructor for NodeReader. It creates the NodeReader and
1.1302 + /// attach it into the given LemonReader. It will use the given
1.1303 + /// node id reader to give back the nodes. The reader will read the
1.1304 + /// section only if the \c _id and the \c nodes_id are the same.
1.1305 + template <typename _IdReader>
1.1306 + NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1.1307 + const std::string& _id = std::string())
1.1308 + : Parent(_reader), id(_id),
1.1309 + idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {}
1.1310 +
1.1311 + /// \brief Destructor.
1.1312 + ///
1.1313 + /// Destructor for NodeReader.
1.1314 + virtual ~NodeReader() {}
1.1315 +
1.1316 + private:
1.1317 + NodeReader(const NodeReader&);
1.1318 + void operator=(const NodeReader&);
1.1319 +
1.1320 + public:
1.1321 +
1.1322 + /// \brief Add a node reader command for the NodeReader.
1.1323 + ///
1.1324 + /// Add a node reader command for the NodeReader.
1.1325 + void readNode(const std::string& name, Node& item) {
1.1326 + if (readers.find(name) != readers.end()) {
1.1327 + ErrorMessage msg;
1.1328 + msg << "Multiple read rule for node: " << name;
1.1329 + throw IOParameterError(msg.message());
1.1330 + }
1.1331 + readers.insert(make_pair(name, &item));
1.1332 + }
1.1333 +
1.1334 + protected:
1.1335 +
1.1336 + /// \brief Gives back true when the SectionReader can process
1.1337 + /// the section with the given header line.
1.1338 + ///
1.1339 + /// It gives back true when the header line start with \c \@nodes,
1.1340 + /// and the header line's id and the reader's id are the same.
1.1341 + virtual bool header(const std::string& line) {
1.1342 + std::istringstream ls(line);
1.1343 + std::string command;
1.1344 + std::string name;
1.1345 + ls >> command >> name;
1.1346 + return command == "@nodes" && name == id;
1.1347 + }
1.1348 +
1.1349 + /// \brief Reader function of the section.
1.1350 + ///
1.1351 + /// It reads the content of the section.
1.1352 + virtual void read(std::istream& is) {
1.1353 + std::string line;
1.1354 + while (getline(is, line)) {
1.1355 + std::istringstream ls(line);
1.1356 + std::string id;
1.1357 + ls >> id;
1.1358 + typename NodeReaders::iterator it = readers.find(id);
1.1359 + if (it != readers.end()) {
1.1360 + *(it->second) = idReader->read(ls);
1.1361 + }
1.1362 + }
1.1363 + }
1.1364 +
1.1365 + private:
1.1366 +
1.1367 + std::string id;
1.1368 +
1.1369 + typedef std::map<std::string, Node*> NodeReaders;
1.1370 + NodeReaders readers;
1.1371 + std::auto_ptr<IdReaderBase<Node> > idReader;
1.1372 + };
1.1373 +
1.1374 + /// \ingroup io_group
1.1375 + /// \brief SectionReader for reading labeled edges.
1.1376 + ///
1.1377 + /// The edges section's header line is \c \@edges \c edges_id, but the
1.1378 + /// \c edges_id may be empty.
1.1379 + ///
1.1380 + /// Each line in the section contains the name of the edge
1.1381 + /// and then the edge id.
1.1382 + ///
1.1383 + /// \relates LemonReader
1.1384 + template <typename _Graph>
1.1385 + class EdgeReader : public CommonSectionReaderBase {
1.1386 + typedef CommonSectionReaderBase Parent;
1.1387 + typedef _Graph Graph;
1.1388 + typedef typename Graph::Edge Edge;
1.1389 + public:
1.1390 +
1.1391 + /// \brief Constructor.
1.1392 + ///
1.1393 + /// Constructor for EdgeReader. It creates the EdgeReader and
1.1394 + /// attach it into the given LemonReader. It will use the given
1.1395 + /// edge id reader to give back the edges. The reader will read the
1.1396 + /// section only if the \c _id and the \c edges_id are the same.
1.1397 + template <typename _IdReader>
1.1398 + EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1.1399 + const std::string& _id = std::string())
1.1400 + : Parent(_reader), id(_id),
1.1401 + idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {}
1.1402 +
1.1403 + /// \brief Destructor.
1.1404 + ///
1.1405 + /// Destructor for EdgeReader.
1.1406 + virtual ~EdgeReader() {}
1.1407 + private:
1.1408 + EdgeReader(const EdgeReader&);
1.1409 + void operator=(const EdgeReader&);
1.1410 +
1.1411 + public:
1.1412 +
1.1413 + /// \brief Add an edge reader command for the EdgeReader.
1.1414 + ///
1.1415 + /// Add an edge reader command for the EdgeReader.
1.1416 + void readEdge(const std::string& name, Edge& item) {
1.1417 + if (readers.find(name) != readers.end()) {
1.1418 + ErrorMessage msg;
1.1419 + msg << "Multiple read rule for edge: " << name;
1.1420 + throw IOParameterError(msg.message());
1.1421 + }
1.1422 + readers.insert(make_pair(name, &item));
1.1423 + }
1.1424 +
1.1425 + protected:
1.1426 +
1.1427 + /// \brief Gives back true when the SectionReader can process
1.1428 + /// the section with the given header line.
1.1429 + ///
1.1430 + /// It gives back true when the header line start with \c \@edges,
1.1431 + /// and the header line's id and the reader's id are the same.
1.1432 + virtual bool header(const std::string& line) {
1.1433 + std::istringstream ls(line);
1.1434 + std::string command;
1.1435 + std::string name;
1.1436 + ls >> command >> name;
1.1437 + return command == "@edges" && name == id;
1.1438 + }
1.1439 +
1.1440 + /// \brief Reader function of the section.
1.1441 + ///
1.1442 + /// It reads the content of the section.
1.1443 + virtual void read(std::istream& is) {
1.1444 + std::string line;
1.1445 + while (getline(is, line)) {
1.1446 + std::istringstream ls(line);
1.1447 + std::string id;
1.1448 + ls >> id;
1.1449 + typename EdgeReaders::iterator it = readers.find(id);
1.1450 + if (it != readers.end()) {
1.1451 + *(it->second) = idReader->read(ls);
1.1452 + }
1.1453 + }
1.1454 + }
1.1455 +
1.1456 + private:
1.1457 +
1.1458 + std::string id;
1.1459 +
1.1460 + typedef std::map<std::string, Edge*> EdgeReaders;
1.1461 + EdgeReaders readers;
1.1462 + std::auto_ptr<IdReaderBase<Edge> > idReader;
1.1463 + };
1.1464 +
1.1465 + /// \ingroup io_group
1.1466 + /// \brief SectionReader for reading labeled undirected edges.
1.1467 + ///
1.1468 + /// The undirected edges section's header line is \c \@undiredges
1.1469 + /// \c undiredges_id, but the \c undiredges_id may be empty.
1.1470 + ///
1.1471 + /// Each line in the section contains the name of the undirected edge
1.1472 + /// and then the undirected edge id.
1.1473 + ///
1.1474 + /// \relates LemonReader
1.1475 + template <typename _Graph>
1.1476 + class UndirEdgeReader : public CommonSectionReaderBase {
1.1477 + typedef CommonSectionReaderBase Parent;
1.1478 + typedef _Graph Graph;
1.1479 + typedef typename Graph::Edge Edge;
1.1480 + typedef typename Graph::UndirEdge UndirEdge;
1.1481 + public:
1.1482 +
1.1483 + /// \brief Constructor.
1.1484 + ///
1.1485 + /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1.1486 + /// attach it into the given LemonReader. It will use the given
1.1487 + /// undirected edge id reader to give back the edges. The reader will
1.1488 + /// read the section only if the \c _id and the \c undiredges_id are
1.1489 + /// the same.
1.1490 + template <typename _IdReader>
1.1491 + UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1.1492 + const std::string& _id = std::string())
1.1493 + : Parent(_reader), id(_id),
1.1494 + undirEdgeIdReader(new IdReader<UndirEdge, _IdReader>(_idReader)),
1.1495 + edgeIdReader(new IdReader<Edge, _IdReader>(_idReader))
1.1496 + {}
1.1497 +
1.1498 + /// \brief Destructor.
1.1499 + ///
1.1500 + /// Destructor for UndirEdgeReader.
1.1501 + virtual ~UndirEdgeReader() {}
1.1502 + private:
1.1503 + UndirEdgeReader(const UndirEdgeReader&);
1.1504 + void operator=(const UndirEdgeReader&);
1.1505 +
1.1506 + public:
1.1507 +
1.1508 + /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1.1509 + ///
1.1510 + /// Add an undirected edge reader command for the UndirEdgeReader.
1.1511 + void readUndirEdge(const std::string& name, UndirEdge& item) {
1.1512 + if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1.1513 + ErrorMessage msg;
1.1514 + msg << "Multiple read rule for undirected edge: " << name;
1.1515 + throw IOParameterError(msg.message());
1.1516 + }
1.1517 + undirEdgeReaders.insert(make_pair(name, &item));
1.1518 + }
1.1519 +
1.1520 + /// \brief Add an edge reader command for the UndirEdgeReader.
1.1521 + ///
1.1522 + /// Add an edge reader command for the UndirEdgeReader.
1.1523 + void readEdge(const std::string& name, Edge& item) {
1.1524 + if (edgeReaders.find(name) != edgeReaders.end()) {
1.1525 + ErrorMessage msg;
1.1526 + msg << "Multiple read rule for edge: " << name;
1.1527 + throw IOParameterError(msg.message());
1.1528 + }
1.1529 + edgeReaders.insert(make_pair(name, &item));
1.1530 + }
1.1531 +
1.1532 + protected:
1.1533 +
1.1534 + /// \brief Gives back true when the SectionReader can process
1.1535 + /// the section with the given header line.
1.1536 + ///
1.1537 + /// It gives back true when the header line start with \c \@edges,
1.1538 + /// and the header line's id and the reader's id are the same.
1.1539 + virtual bool header(const std::string& line) {
1.1540 + std::istringstream ls(line);
1.1541 + std::string command;
1.1542 + std::string name;
1.1543 + ls >> command >> name;
1.1544 + return command == "@undiredges" && name == id;
1.1545 + }
1.1546 +
1.1547 + /// \brief Reader function of the section.
1.1548 + ///
1.1549 + /// It reads the content of the section.
1.1550 + virtual void read(std::istream& is) {
1.1551 + std::string line;
1.1552 + while (getline(is, line)) {
1.1553 + std::istringstream ls(line);
1.1554 + std::string id;
1.1555 + ls >> id;
1.1556 + {
1.1557 + typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1.1558 + if (it != undirEdgeReaders.end()) {
1.1559 + *(it->second) = undirEdgeIdReader->read(ls);
1.1560 + break;
1.1561 + }
1.1562 + } {
1.1563 + typename EdgeReaders::iterator it = edgeReaders.find(id);
1.1564 + if (it != edgeReaders.end()) {
1.1565 + *(it->second) = edgeIdReader->read(ls);
1.1566 + break;
1.1567 + }
1.1568 + }
1.1569 + }
1.1570 + }
1.1571 +
1.1572 + private:
1.1573 +
1.1574 + std::string id;
1.1575 +
1.1576 + typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1.1577 + UndirEdgeReaders undirEdgeReaders;
1.1578 + std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1.1579 +
1.1580 + typedef std::map<std::string, Edge*> EdgeReaders;
1.1581 + EdgeReaders edgeReaders;
1.1582 + std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1.1583 + };
1.1584 +
1.1585 + /// \ingroup io_group
1.1586 + /// \brief SectionReader for attributes.
1.1587 + ///
1.1588 + /// The lemon format can store multiple attribute set. Each set has
1.1589 + /// the header line \c \@attributes \c attributeset_id, but the
1.1590 + /// attributeset_id may be empty.
1.1591 + ///
1.1592 + /// The attributeset section contains several lines. Each of them starts
1.1593 + /// with an attribute and then a the value for the id.
1.1594 + ///
1.1595 + /// \relates LemonReader
1.1596 + template <typename _Traits = DefaultReaderTraits>
1.1597 + class AttributeReader : public CommonSectionReaderBase {
1.1598 + typedef CommonSectionReaderBase Parent;
1.1599 + typedef _Traits Traits;
1.1600 + public:
1.1601 + /// \brief Constructor.
1.1602 + ///
1.1603 + /// Constructor for AttributeReader. It creates the AttributeReader and
1.1604 + /// attach it into the given LemonReader. The reader process a section
1.1605 + /// only if the \c section_id and the \c _id are the same.
1.1606 + AttributeReader(LemonReader& _reader,
1.1607 + const std::string& _id = std::string())
1.1608 + : Parent(_reader), id(_id) {}
1.1609 +
1.1610 + /// \brief Destructor.
1.1611 + ///
1.1612 + /// Destructor for AttributeReader.
1.1613 + virtual ~AttributeReader() {
1.1614 + for (typename Readers::iterator it = readers.begin();
1.1615 + it != readers.end(); ++it) {
1.1616 + delete it->second;
1.1617 + }
1.1618 + }
1.1619 +
1.1620 + private:
1.1621 + AttributeReader(const AttributeReader&);
1.1622 + void operator=(AttributeReader&);
1.1623 +
1.1624 + public:
1.1625 + /// \brief Add an attribute reader command for the reader.
1.1626 + ///
1.1627 + /// Add an attribute reader command for the reader.
1.1628 + template <typename Value>
1.1629 + AttributeReader& readAttribute(const std::string& id, Value& value) {
1.1630 + return readAttribute<typename Traits::template Reader<Value> >
1.1631 + (id, value);
1.1632 + }
1.1633 +
1.1634 + /// \brief Add an attribute reader command for the reader.
1.1635 + ///
1.1636 + /// Add an attribute reader command for the reader.
1.1637 + template <typename Reader, typename Value>
1.1638 + AttributeReader& readAttribute(const std::string& name, Value& value,
1.1639 + const Reader& reader = Reader()) {
1.1640 + if (readers.find(name) != readers.end()) {
1.1641 + ErrorMessage msg;
1.1642 + msg << "Multiple read rule for attribute: " << name;
1.1643 + throw IOParameterError(msg.message());
1.1644 + }
1.1645 + readers.insert(make_pair(name, new ValueReader<Value, Reader>
1.1646 + (value, reader)));
1.1647 + return *this;
1.1648 + }
1.1649 +
1.1650 + protected:
1.1651 +
1.1652 + /// \brief Gives back true when the SectionReader can process
1.1653 + /// the section with the given header line.
1.1654 + ///
1.1655 + /// It gives back true when the header line start with \c \@attributes,
1.1656 + /// and the header line's id and the attributeset's id are the same.
1.1657 + bool header(const std::string& line) {
1.1658 + std::istringstream ls(line);
1.1659 + std::string command;
1.1660 + std::string name;
1.1661 + ls >> command >> name;
1.1662 + return command == "@attributes" && name == id;
1.1663 + }
1.1664 +
1.1665 + /// \brief Reader function of the section.
1.1666 + ///
1.1667 + /// It reads the content of the section.
1.1668 + void read(std::istream& is) {
1.1669 + std::string line;
1.1670 + while (getline(is, line)) {
1.1671 + std::istringstream ls(line);
1.1672 + std::string id;
1.1673 + ls >> id;
1.1674 + typename Readers::iterator it = readers.find(id);
1.1675 + if (it != readers.end()) {
1.1676 + it->second->read(ls);
1.1677 + }
1.1678 + }
1.1679 + }
1.1680 +
1.1681 + private:
1.1682 + std::string id;
1.1683 +
1.1684 + typedef std::map<std::string, ValueReaderBase*> Readers;
1.1685 + Readers readers;
1.1686 + };
1.1687 +
1.1688 + /// \ingroup io_group
1.1689 + /// \brief SectionReader for retrieve what is in the file.
1.1690 + ///
1.1691 + /// SectionReader for retrieve what is in the file. If you want
1.1692 + /// to know which sections, maps and items are in the file
1.1693 + /// use the next code:
1.1694 + /// \code
1.1695 + /// LemonReader reader("input.lgf");
1.1696 + /// ContentReader content(reader);
1.1697 + /// reader.run();
1.1698 + /// \endcode
1.1699 + class ContentReader : public LemonReader::SectionReader {
1.1700 + typedef LemonReader::SectionReader Parent;
1.1701 + public:
1.1702 + /// \brief Constructor.
1.1703 + ///
1.1704 + /// Constructor for
1.1705 + ContentReader(LemonReader& _reader) : Parent(_reader) {}
1.1706 +
1.1707 + /// \brief Desctructor.
1.1708 + ///
1.1709 + /// Desctructor.
1.1710 + virtual ~ContentReader() {}
1.1711 +
1.1712 + /// \brief Gives back how many nodesets are in the file.
1.1713 + ///
1.1714 + /// Gives back how many nodesets are in the file.
1.1715 + int nodeSetNum() const {
1.1716 + return nodesets.size();
1.1717 + }
1.1718 +
1.1719 + /// \brief Gives back the name of nodeset on the indiced position.
1.1720 + ///
1.1721 + /// Gives back the name of nodeset on the indiced position.
1.1722 + std::string nodeSetName(int index) const {
1.1723 + return nodesets[index].name;
1.1724 + }
1.1725 +
1.1726 + /// \brief Gives back the map names of nodeset on the indiced position.
1.1727 + ///
1.1728 + /// Gives back the map names of nodeset on the indiced position.
1.1729 + const std::vector<std::string>& nodeSetMaps(int index) const {
1.1730 + return nodesets[index].items;
1.1731 + }
1.1732 +
1.1733 + /// \brief Gives back how many edgesets are in the file.
1.1734 + ///
1.1735 + /// Gives back how many edgesets are in the file.
1.1736 + int edgeSetNum() const {
1.1737 + return edgesets.size();
1.1738 + }
1.1739 +
1.1740 + /// \brief Gives back the name of edgeset on the indiced position.
1.1741 + ///
1.1742 + /// Gives back the name of edgeset on the indiced position.
1.1743 + std::string edgeSetName(int index) const {
1.1744 + return edgesets[index].name;
1.1745 + }
1.1746 +
1.1747 + /// \brief Gives back the map names of edgeset on the indiced position.
1.1748 + ///
1.1749 + /// Gives back the map names of edgeset on the indiced position.
1.1750 + const std::vector<std::string>& edgeSetMaps(int index) const {
1.1751 + return edgesets[index].items;
1.1752 + }
1.1753 +
1.1754 + /// \brief Gives back how many undirected edgesets are in the file.
1.1755 + ///
1.1756 + /// Gives back how many undirected edgesets are in the file.
1.1757 + int undirEdgeSetNum() const {
1.1758 + return undiredgesets.size();
1.1759 + }
1.1760 +
1.1761 + /// \brief Gives back the name of undirected edgeset on the indiced
1.1762 + /// position.
1.1763 + ///
1.1764 + /// Gives back the name of undirected edgeset on the indiced position.
1.1765 + std::string undirEdgeSetName(int index) const {
1.1766 + return undiredgesets[index].name;
1.1767 + }
1.1768 +
1.1769 + /// \brief Gives back the map names of undirected edgeset on the indiced
1.1770 + /// position.
1.1771 + ///
1.1772 + /// Gives back the map names of undirected edgeset on the indiced position.
1.1773 + const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1.1774 + return undiredgesets[index].items;
1.1775 + }
1.1776 +
1.1777 + /// \brief Gives back how many labeled nodes section are in the file.
1.1778 + ///
1.1779 + /// Gives back how many labeled nodes section are in the file.
1.1780 + int nodesNum() const {
1.1781 + return nodes.size();
1.1782 + }
1.1783 +
1.1784 + /// \brief Gives back the name of labeled nodes section on the indiced
1.1785 + /// position.
1.1786 + ///
1.1787 + /// Gives back the name of labeled nodes section on the indiced position.
1.1788 + std::string nodesName(int index) const {
1.1789 + return nodes[index].name;
1.1790 + }
1.1791 +
1.1792 + /// \brief Gives back the names of the labeled nodes in the indiced
1.1793 + /// section.
1.1794 + ///
1.1795 + /// Gives back the names of the labeled nodes in the indiced section.
1.1796 + const std::vector<std::string>& nodesItems(int index) const {
1.1797 + return nodes[index].items;
1.1798 + }
1.1799 +
1.1800 + /// \brief Gives back how many labeled edges section are in the file.
1.1801 + ///
1.1802 + /// Gives back how many labeled edges section are in the file.
1.1803 + int edgesNum() const {
1.1804 + return edges.size();
1.1805 + }
1.1806 +
1.1807 + /// \brief Gives back the name of labeled edges section on the indiced
1.1808 + /// position.
1.1809 + ///
1.1810 + /// Gives back the name of labeled edges section on the indiced position.
1.1811 + std::string edgesName(int index) const {
1.1812 + return edges[index].name;
1.1813 + }
1.1814 +
1.1815 + /// \brief Gives back the names of the labeled edges in the indiced
1.1816 + /// section.
1.1817 + ///
1.1818 + /// Gives back the names of the labeled edges in the indiced section.
1.1819 + const std::vector<std::string>& edgesItems(int index) const {
1.1820 + return edges[index].items;
1.1821 + }
1.1822 +
1.1823 + /// \brief Gives back how many labeled undirected edges section are
1.1824 + /// in the file.
1.1825 + ///
1.1826 + /// Gives back how many labeled undirected edges section are in the file.
1.1827 + int undirEdgesNum() const {
1.1828 + return undiredges.size();
1.1829 + }
1.1830 +
1.1831 + /// \brief Gives back the name of labeled undirected edges section
1.1832 + /// on the indiced position.
1.1833 + ///
1.1834 + /// Gives back the name of labeled undirected edges section on the
1.1835 + /// indiced position.
1.1836 + std::string undirEdgesName(int index) const {
1.1837 + return undiredges[index].name;
1.1838 + }
1.1839 +
1.1840 + /// \brief Gives back the names of the labeled undirected edges in
1.1841 + /// the indiced section.
1.1842 + ///
1.1843 + /// Gives back the names of the labeled undirected edges in the
1.1844 + /// indiced section.
1.1845 + const std::vector<std::string>& undirEdgesItems(int index) const {
1.1846 + return undiredges[index].items;
1.1847 + }
1.1848 +
1.1849 +
1.1850 + /// \brief Gives back how many attributes section are in the file.
1.1851 + ///
1.1852 + /// Gives back how many attributes section are in the file.
1.1853 + int attributesNum() const {
1.1854 + return attributes.size();
1.1855 + }
1.1856 +
1.1857 + /// \brief Gives back the name of attributes section on the indiced
1.1858 + /// position.
1.1859 + ///
1.1860 + /// Gives back the name of attributes section on the indiced position.
1.1861 + std::string attributesName(int index) const {
1.1862 + return attributes[index].name;
1.1863 + }
1.1864 +
1.1865 + /// \brief Gives back the names of the attributes in the indiced section.
1.1866 + ///
1.1867 + /// Gives back the names of the attributes in the indiced section.
1.1868 + const std::vector<std::string>& attributesItems(int index) const {
1.1869 + return attributes[index].items;
1.1870 + }
1.1871 +
1.1872 + const std::vector<std::string>& otherSections() const {
1.1873 + return sections;
1.1874 + }
1.1875 +
1.1876 + protected:
1.1877 +
1.1878 + /// \brief Gives back true when the SectionReader can process
1.1879 + /// the section with the given header line.
1.1880 + ///
1.1881 + /// It gives back true when the section is common section.
1.1882 + bool header(const std::string& line) {
1.1883 + std::istringstream ls(line);
1.1884 + std::string command, name;
1.1885 + ls >> command >> name;
1.1886 + if (command == "@nodeset") {
1.1887 + current = command;
1.1888 + nodesets.push_back(SectionInfo(name));
1.1889 + } else if (command == "@edgeset") {
1.1890 + current = command;
1.1891 + edgesets.push_back(SectionInfo(name));
1.1892 + } else if (command == "@undiredgeset") {
1.1893 + current = command;
1.1894 + undiredgesets.push_back(SectionInfo(name));
1.1895 + } else if (command == "@nodes") {
1.1896 + current = command;
1.1897 + nodes.push_back(SectionInfo(name));
1.1898 + } else if (command == "@edges") {
1.1899 + current = command;
1.1900 + edges.push_back(SectionInfo(name));
1.1901 + } else if (command == "@undiredges") {
1.1902 + current = command;
1.1903 + undiredges.push_back(SectionInfo(name));
1.1904 + } else if (command == "@attributes") {
1.1905 + current = command;
1.1906 + attributes.push_back(SectionInfo(name));
1.1907 + } else {
1.1908 + sections.push_back(line);
1.1909 + return false;
1.1910 + }
1.1911 + return true;
1.1912 + }
1.1913 +
1.1914 + /// \brief Retrieve the items from various sections.
1.1915 + ///
1.1916 + /// Retrieve the items from various sections.
1.1917 + void read(std::istream& is) {
1.1918 + if (current == "@nodeset") {
1.1919 + readMapNames(is, nodesets.back().items);
1.1920 + } else if (current == "@edgeset") {
1.1921 + readMapNames(is, edgesets.back().items);
1.1922 + } else if (current == "@undiredgeset") {
1.1923 + readMapNames(is, undiredgesets.back().items);
1.1924 + } else if (current == "@nodes") {
1.1925 + readItemNames(is, nodes.back().items);
1.1926 + } else if (current == "@edges") {
1.1927 + readItemNames(is, edges.back().items);
1.1928 + } else if (current == "@undiredges") {
1.1929 + readItemNames(is, undiredges.back().items);
1.1930 + } else if (current == "@attributes") {
1.1931 + readItemNames(is, attributes.back().items);
1.1932 + }
1.1933 + }
1.1934 +
1.1935 + private:
1.1936 +
1.1937 + void readMapNames(std::istream& is, std::vector<std::string>& maps) {
1.1938 + std::string line, id;
1.1939 + std::getline(is, line);
1.1940 + std::istringstream ls(line);
1.1941 + while (ls >> id) {
1.1942 + maps.push_back(id);
1.1943 + }
1.1944 + while (getline(is, line));
1.1945 + }
1.1946 +
1.1947 + void readItemNames(std::istream& is, std::vector<std::string>& maps) {
1.1948 + std::string line, id;
1.1949 + while (std::getline(is, line)) {
1.1950 + std::istringstream ls(line);
1.1951 + ls >> id;
1.1952 + maps.push_back(id);
1.1953 + }
1.1954 + }
1.1955 +
1.1956 + struct SectionInfo {
1.1957 + std::string name;
1.1958 + std::vector<std::string> items;
1.1959 +
1.1960 + SectionInfo(const std::string& _name) : name(_name) {}
1.1961 + };
1.1962 +
1.1963 + std::vector<SectionInfo> nodesets;
1.1964 + std::vector<SectionInfo> edgesets;
1.1965 + std::vector<SectionInfo> undiredgesets;
1.1966 +
1.1967 + std::vector<SectionInfo> nodes;
1.1968 + std::vector<SectionInfo> edges;
1.1969 + std::vector<SectionInfo> undiredges;
1.1970 +
1.1971 + std::vector<SectionInfo> attributes;
1.1972 +
1.1973 + std::vector<std::string> sections;
1.1974 +
1.1975 + std::string current;
1.1976 +
1.1977 + };
1.1978 +
1.1979 +}
1.1980 +#endif