deba@1408: /* -*- C++ -*- deba@1408: * alpar@1956: * This file is a part of LEMON, a generic C++ optimization library alpar@1956: * alpar@2391: * Copyright (C) 2003-2007 alpar@1956: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@1408: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@1408: * deba@1408: * Permission to use, modify and distribute this software is granted deba@1408: * provided that this copyright notice appears in all copies. For deba@1408: * precise terms see the accompanying LICENSE file. deba@1408: * deba@1408: * This software is provided "AS IS" with no warranty of any kind, deba@1408: * express or implied, and with no claim as to its suitability for any deba@1408: * purpose. deba@1408: * deba@1408: */ deba@1408: deba@2084: ///\ingroup lemon_io deba@1408: ///\file deba@1408: ///\brief Lemon Format reader. deba@1408: deba@1421: deba@1408: #ifndef LEMON_LEMON_READER_H deba@1408: #define LEMON_LEMON_READER_H deba@1408: deba@1421: deba@1408: #include deba@1408: #include deba@1408: #include deba@1408: #include deba@1408: #include deba@1408: #include deba@1408: #include deba@1408: deba@1408: #include deba@1421: #include deba@1993: #include deba@1409: #include deba@1408: alpar@2207: #include deba@1705: deba@1476: #include alpar@2260: #include deba@1408: deba@1408: namespace lemon { deba@1408: deba@1421: namespace _reader_bits { deba@1476: deba@1845: template deba@1845: bool operator<(T, T) { deba@1901: throw DataFormatError("Label is not comparable"); deba@1845: } deba@1845: deba@1845: template deba@1845: struct Less { deba@1845: bool operator()(const T& p, const T& q) const { deba@1845: return p < q; deba@1845: } deba@1845: }; deba@2467: deba@1476: template deba@1901: class ItemLabelReader { deba@1476: public: deba@1476: deba@1901: bool isLabelReader() { return true; } deba@1476: deba@1901: void readLabel(std::istream&, Item&) {} deba@1476: deba@1901: template deba@1476: struct Constraints { deba@1476: void constraints() { deba@1901: bool b = reader.isLabelReader(); deba@1476: ignore_unused_variable_warning(b); deba@1492: Item item; deba@1901: reader.readLabel(is, item); deba@1476: } deba@1901: _ItemLabelReader& reader; deba@1476: std::istream& is; deba@1476: }; deba@1476: deba@1476: }; deba@1492: deba@1492: template deba@1492: class ItemReader { deba@1492: public: deba@1492: void read(std::istream&, Item&) {} deba@1492: deba@1492: template deba@1492: struct Constraints { deba@1492: void constraints() { deba@1492: Item item; deba@1492: reader.read(is, item); deba@1492: } deba@1492: _ItemReader& reader; deba@1492: std::istream& is; deba@1492: }; deba@1492: deba@1492: }; deba@1421: deba@1705: template deba@1705: struct Ref { typedef Map& Type; }; deba@1705: template deba@1705: struct Arg { typedef Map& Type; }; deba@1705: deba@1705: template deba@1705: class ForwardComposeMap { deba@1421: public: klao@1909: typedef typename Graph::UEdge Key; deba@1705: typedef typename Map::Value Value; deba@1705: deba@1705: ForwardComposeMap(const Graph& _graph, typename Arg::Type _map) deba@1705: : graph(_graph), map(_map) {} deba@1421: deba@1705: void set(const Key& key, const Value& val) { deba@1705: map.set(graph.direct(key, true), val); deba@1421: } deba@1421: deba@1421: private: deba@2282: const Graph& graph; deba@1705: typename Ref::Type map; deba@1421: }; deba@1421: deba@1705: template deba@1705: ForwardComposeMap deba@1705: forwardComposeMap(const Graph& graph, const Map& map) { deba@1705: return ForwardComposeMap(graph, map); deba@1421: } deba@1421: deba@1705: template deba@1705: ForwardComposeMap deba@1705: forwardComposeMap(const Graph& graph, Map& map) { deba@1705: return ForwardComposeMap(graph, map); deba@1421: } deba@1705: deba@1705: template deba@1705: class BackwardComposeMap { deba@1705: public: klao@1909: typedef typename Graph::UEdge Key; deba@1705: typedef typename Map::Value Value; deba@1705: deba@1705: BackwardComposeMap(const Graph& _graph, typename Arg::Type _map) deba@1705: : graph(_graph), map(_map) {} deba@1705: deba@1705: void set(const Key& key, const Value& val) { deba@1705: map.set(graph.direct(key, false), val); deba@1705: } deba@1705: deba@1705: private: deba@2282: const Graph& graph; deba@1705: typename Ref::Type map; deba@1705: }; deba@1705: deba@1705: deba@1705: template deba@1705: BackwardComposeMap deba@1705: backwardComposeMap(const Graph& graph, const Map& map) { deba@1705: return BackwardComposeMap(graph, map); deba@1705: } deba@1705: deba@1705: template deba@1705: BackwardComposeMap deba@1705: backwardComposeMap(const Graph& graph, Map& map) { deba@1705: return BackwardComposeMap(graph, map); deba@1705: } deba@1705: deba@1705: template deba@1705: struct Ref > { deba@1705: typedef ForwardComposeMap Type; deba@1705: }; deba@1705: template deba@1705: struct Arg > { deba@1705: typedef const ForwardComposeMap& Type; deba@1705: }; deba@1705: deba@1705: template deba@1705: struct Ref > { deba@1705: typedef BackwardComposeMap Type; deba@1705: }; deba@1705: template deba@1705: struct Arg > { deba@1705: typedef const BackwardComposeMap& Type; deba@1705: }; deba@1705: deba@1705: template alpar@2207: struct Ref > { alpar@2207: typedef dim2::XMap Type; deba@1705: }; deba@1705: template alpar@2207: struct Arg > { alpar@2207: typedef const dim2::XMap& Type; deba@1705: }; deba@1705: deba@1705: template alpar@2207: struct Ref > { alpar@2207: typedef dim2::YMap Type; deba@1705: }; deba@1705: template alpar@2207: struct Arg > { alpar@2207: typedef const dim2::YMap& Type; deba@1705: }; deba@1705: deba@1845: deba@1845: template deba@1845: class MapReaderBase; deba@1845: deba@1845: template deba@1845: class MapInverterBase : public MapReaderBase<_Item> { deba@1845: public: deba@1845: typedef _Item Item; deba@1845: virtual void read(std::istream&, const Item&) = 0; deba@1845: virtual Item read(std::istream&) const = 0; deba@1845: deba@1845: virtual MapInverterBase<_Item>* getInverter() { deba@1845: return this; deba@1845: } deba@1845: }; deba@1845: deba@1845: template deba@1845: class MapReaderInverter : public MapInverterBase<_Item> { deba@1845: public: deba@1845: typedef _Item Item; deba@1845: typedef _Reader Reader; deba@1845: typedef typename Reader::Value Value; deba@1845: typedef _Map Map; deba@1845: typedef std::map > Inverse; deba@1845: deba@1845: typename _reader_bits::Ref::Type map; deba@1845: Reader reader; deba@1845: Inverse inverse; deba@1845: deba@1845: MapReaderInverter(typename _reader_bits::Arg::Type _map, deba@1845: const Reader& _reader) deba@1845: : map(_map), reader(_reader) {} deba@1845: deba@1845: virtual ~MapReaderInverter() {} deba@1845: deba@1845: virtual void read(std::istream& is, const Item& item) { deba@1845: Value value; deba@1845: reader.read(is, value); deba@1845: map.set(item, value); deba@1845: typename Inverse::iterator it = inverse.find(value); deba@1845: if (it == inverse.end()) { deba@1845: inverse.insert(std::make_pair(value, item)); deba@1845: } else { deba@1901: throw DataFormatError("Multiple label occurence"); deba@1845: } deba@1845: } deba@1845: deba@1845: virtual Item read(std::istream& is) const { deba@1845: Value value; deba@1845: reader.read(is, value); deba@1845: typename Inverse::const_iterator it = inverse.find(value); deba@1845: if (it != inverse.end()) { deba@1845: return it->second; deba@1845: } else { deba@2461: ErrorMessage msg; deba@2467: msg << "Invalid label error"; deba@2461: throw DataFormatError(msg.message()); deba@1845: } deba@1845: } deba@1845: }; deba@1845: deba@1845: template deba@1845: class SkipReaderInverter : public MapInverterBase<_Item> { deba@1845: public: deba@1845: typedef _Item Item; deba@1845: typedef _Reader Reader; deba@1845: typedef typename Reader::Value Value; deba@1845: typedef std::map > Inverse; deba@1845: deba@1845: Reader reader; deba@1845: deba@1845: SkipReaderInverter(const Reader& _reader) deba@1845: : reader(_reader) {} deba@1845: deba@1845: virtual ~SkipReaderInverter() {} deba@1845: deba@1845: virtual void read(std::istream& is, const Item& item) { deba@1845: Value value; deba@1845: reader.read(is, value); deba@1845: typename Inverse::iterator it = inverse.find(value); deba@1845: if (it == inverse.end()) { deba@1845: inverse.insert(std::make_pair(value, item)); deba@1845: } else { deba@1901: throw DataFormatError("Multiple label occurence error"); deba@1845: } deba@1845: } deba@1845: deba@1845: virtual Item read(std::istream& is) const { deba@1845: Value value; deba@2467: reader.read(is, value); deba@1845: typename Inverse::const_iterator it = inverse.find(value); deba@1845: if (it != inverse.end()) { deba@1845: return it->second; deba@1845: } else { deba@2461: ErrorMessage msg; deba@2461: msg << "Invalid label error: " << value; deba@2461: throw DataFormatError(msg.message()); deba@1845: } deba@1845: } deba@1845: deba@1845: private: deba@1845: Inverse inverse; deba@1845: }; deba@1845: deba@1845: template deba@1845: class MapReaderBase { deba@1845: public: deba@1845: typedef _Item Item; deba@1845: deba@1845: MapReaderBase() { _touched = false; } deba@1845: deba@2502: void touch(bool value = true) { _touched = value; } deba@1845: bool touched() const { return _touched; } deba@1845: deba@1845: virtual ~MapReaderBase() {} deba@1845: deba@1845: virtual void read(std::istream& is, const Item& item) = 0; deba@1845: virtual MapInverterBase<_Item>* getInverter() = 0; deba@1845: deba@1845: private: deba@1845: bool _touched; deba@1845: deba@1845: }; deba@1845: deba@1845: template deba@1845: class MapReader : public MapReaderBase<_Item> { deba@1845: public: deba@1845: typedef _Map Map; deba@1845: typedef _Reader Reader; deba@1845: typedef typename Reader::Value Value; deba@1845: typedef _Item Item; deba@1845: deba@1845: typename _reader_bits::Ref::Type map; deba@1845: Reader reader; deba@1845: deba@1845: MapReader(typename _reader_bits::Arg::Type _map, deba@1845: const Reader& _reader) deba@1845: : map(_map), reader(_reader) {} deba@1845: deba@1845: virtual ~MapReader() {} deba@1845: deba@1845: virtual void read(std::istream& is, const Item& item) { deba@1845: Value value; deba@1845: reader.read(is, value); deba@1845: map.set(item, value); deba@1845: } deba@1845: deba@1845: virtual MapInverterBase<_Item>* getInverter() { deba@1845: return new MapReaderInverter(map, reader); deba@1845: } deba@1845: }; deba@1845: deba@1845: deba@1845: template deba@1845: class SkipReader : public MapReaderBase<_Item> { deba@1845: public: deba@1845: typedef _Reader Reader; deba@1845: typedef typename Reader::Value Value; deba@1845: typedef _Item Item; deba@1845: deba@1845: Reader reader; deba@1845: SkipReader(const Reader& _reader) : reader(_reader) {} deba@1845: deba@1845: virtual ~SkipReader() {} deba@1845: deba@1845: virtual void read(std::istream& is, const Item&) { deba@1845: Value value; deba@1845: reader.read(is, value); deba@1845: } deba@1845: deba@1845: virtual MapInverterBase* getInverter() { deba@1845: return new SkipReaderInverter(reader); deba@1845: } deba@1845: }; deba@1845: deba@1845: template deba@1901: class LabelReaderBase { deba@1845: public: deba@1845: typedef _Item Item; deba@1901: virtual ~LabelReaderBase() {} deba@1845: virtual Item read(std::istream& is) const = 0; deba@1901: virtual bool isLabelReader() const = 0; deba@2467: virtual LabelReaderBase<_Item>* clone() const = 0; deba@1845: }; deba@1845: deba@1901: template deba@1901: class LabelReader : public LabelReaderBase<_Item> { deba@1845: public: deba@1845: typedef _Item Item; deba@1901: typedef _BoxedLabelReader BoxedLabelReader; deba@1845: deba@2467: const BoxedLabelReader& labelReader; deba@2467: deba@2467: LabelReader(const BoxedLabelReader& _labelReader) deba@2467: : labelReader(_labelReader) {} deba@1845: deba@1845: virtual Item read(std::istream& is) const { deba@1845: Item item; deba@2467: labelReader.readLabel(is, item); deba@1845: return item; deba@1845: } deba@1845: deba@1901: virtual bool isLabelReader() const { deba@2467: return labelReader.isLabelReader(); deba@2467: } deba@2467: deba@2467: LabelReader* clone() const { deba@2467: return new LabelReader(labelReader); deba@1845: } deba@1845: }; deba@1845: deba@1845: template deba@1845: class ItemStore { deba@1845: public: deba@1845: deba@1845: typedef _Item Item; deba@1845: deba@1845: ItemStore(Item& _item) : item(&_item) { deba@1845: _touched = false; deba@1845: } deba@1845: deba@1845: void touch() { _touched = true; } deba@1845: bool touched() const { return _touched; } deba@1845: deba@1845: void read(const Item& _item) { deba@1845: *item = _item; deba@1845: } deba@1845: deba@1845: private: deba@1845: Item* item; deba@1845: bool _touched; deba@1845: }; deba@1845: deba@1845: class ValueReaderBase { deba@1845: public: deba@1845: virtual void read(std::istream&) {}; deba@1846: ValueReaderBase() { _touched = false; } deba@1846: deba@1846: void touch() { _touched = true; } deba@1846: bool touched() const { return _touched; } deba@1846: deba@1845: virtual ~ValueReaderBase() {} deba@1846: private: deba@1846: bool _touched; deba@1845: }; deba@1845: deba@1845: template deba@1845: class ValueReader : public ValueReaderBase { deba@1845: public: deba@1845: typedef _Value Value; deba@1845: typedef _Reader Reader; deba@1845: deba@1845: ValueReader(Value& _value, const Reader& _reader) deba@1845: : value(_value), reader(_reader) {} deba@1845: deba@1845: virtual void read(std::istream& is) { deba@1845: reader.read(is, value); deba@1845: } deba@1845: private: deba@1845: Value& value; deba@1845: Reader reader; deba@1845: }; deba@1845: deba@1421: } deba@1421: deba@2084: /// \ingroup lemon_io deba@1408: /// \brief Lemon Format reader class. deba@1408: /// deba@1409: /// The Lemon Format contains several sections. We do not want to deba@1409: /// determine what sections are in a lemon file we give only a framework deba@1409: /// to read a section oriented format. deba@1409: /// athos@2334: /// In the Lemon Format each section starts with a line containing a athos@2334: /// \c \@ character on the first not white space position. This line athos@2334: /// is the header line of the section. Each of the next lines belong athos@2334: /// to this section until a line starting with \c \@ character is athos@2334: /// found. This line can start a new section or it can close the athos@2334: /// file with the \c \@end line. The file format ignores the empty athos@2334: /// and comment lines. The line is comment line if it starts with a athos@2334: /// \c # character. deba@1409: /// deba@1409: /// The framework provides an abstract LemonReader::SectionReader class athos@2334: /// that defines the interface of a SectionReader. The SectionReader athos@2334: /// has the \c header() member function that gets a header line string and athos@2334: /// decides if it wants to process the next section. Several SectionReaders athos@2334: /// can be attached to a LemonReader and the first attached that can athos@2334: /// process the section will be used. Its \c read() member will be called athos@2334: /// with a stream containing the section. From this stream the empty and deba@1427: /// comment lines are filtered out. deba@1409: /// deba@1409: /// \relates GraphReader deba@1409: /// \relates NodeSetReader deba@1409: /// \relates EdgeSetReader deba@1409: /// \relates NodesReader deba@1409: /// \relates EdgesReader deba@1409: /// \relates AttributeReader deba@1408: class LemonReader { deba@1408: private: deba@1408: deba@1408: class FilterStreamBuf : public std::streambuf { deba@1408: public: deba@1408: deba@1408: typedef std::streambuf Parent; deba@1408: typedef Parent::char_type char_type; deba@1408: FilterStreamBuf(std::istream& is, int& num) deba@1408: : _is(is), _base(0), _eptr(0), deba@1408: _num(num), skip_state(after_endl) {} deba@1408: deba@1408: protected: deba@1408: deba@1408: enum skip_state_type { deba@1408: no_skip, deba@1408: after_endl, deba@1427: comment_line deba@1408: }; deba@1408: deba@1408: char_type small_buf[1]; deba@1408: deba@1408: deba@1408: std::istream& _is; deba@1408: deba@1408: char_type* _base; deba@1408: char_type* _eptr; deba@1408: deba@1408: int& _num; deba@1408: deba@1408: skip_state_type skip_state; deba@1408: deba@1408: deba@1408: char_type* base() { return _base; } deba@1408: deba@1408: char_type* eptr() { return _eptr; } deba@1408: deba@2084: int_type blen() { return _eptr - _base; } deba@1408: deba@2084: void setb(char_type* buf, int_type len) { deba@1408: _base = buf; deba@1408: _eptr = buf + len; deba@1408: } deba@1408: ladanyi@1722: virtual std::streambuf* setbuf(char *buf, std::streamsize len) { deba@1408: if (base()) return 0; deba@2386: if (buf != 0 && len >= int(sizeof(small_buf))) { deba@1408: setb(buf, len); deba@1408: } else { deba@1408: setb(small_buf, sizeof(small_buf)); deba@1408: } deba@1408: setg(0, 0, 0); deba@1408: return this; deba@1408: } deba@1408: deba@1408: bool put_char(char c) { deba@1408: switch (skip_state) { deba@1408: case no_skip: deba@1408: switch (c) { deba@1408: case '\n': deba@1408: skip_state = after_endl; deba@1408: return true; deba@1408: default: deba@1408: return true; deba@1408: } deba@1408: case after_endl: deba@1408: switch (c) { deba@1408: case '@': deba@1408: return false; deba@1408: case '\n': deba@1408: return false; deba@1408: case '#': deba@1427: skip_state = comment_line; deba@1408: return false; deba@1408: default: deba@1408: if (!isspace(c)) { deba@1408: skip_state = no_skip; deba@1408: return true; deba@1408: } else { deba@1408: return false; deba@1408: } deba@1408: } deba@1408: break; deba@1427: case comment_line: deba@1408: switch (c) { deba@1408: case '\n': deba@1408: skip_state = after_endl; deba@1408: return false; deba@1408: default: deba@1408: return false; deba@1408: } deba@1408: } deba@1408: return false; deba@1408: } deba@1408: deba@2084: virtual int_type underflow() { deba@1408: char c; deba@2502: if ((c = _is.peek()) != EOF) { deba@1408: if (c == '@') { deba@1408: return EOF; deba@1408: } deba@1408: } else { deba@1408: return EOF; deba@1408: } deba@1408: char_type *ptr; deba@1408: for (ptr = base(); ptr != eptr(); ++ptr) { deba@2502: if ((c = _is.get()) != EOF) { deba@1408: if (c == '\n') ++_num; deba@1408: if (put_char(c)) { deba@1408: *ptr = c; deba@1408: } else { deba@1408: if (skip_state == after_endl && c == '@') { deba@2502: _is.putback(c); deba@1408: break; deba@1408: } deba@1408: --ptr; deba@1408: } deba@1408: } else { deba@1408: break; deba@1408: } deba@1408: } deba@1408: setg(base(), base(), ptr); deba@1408: return *base(); deba@1408: } deba@1408: deba@2084: virtual int_type sync() { deba@1408: return EOF; deba@1408: } deba@2460: deba@2460: public: deba@2460: deba@2460: int line_num() const { deba@2460: int r = _num; deba@2460: for (char_type* p = gptr(); p != egptr(); ++p) { deba@2460: if (*p == '\n') --r; deba@2460: } deba@2460: return r; deba@2460: } deba@2460: deba@1408: }; deba@1408: deba@2502: static void skipPreSection(std::istream& is, int& line_num) { deba@2502: enum skip_state_type { skip, after_endl }; deba@2502: deba@2502: skip_state_type skip_state = after_endl; deba@2502: char c; deba@2502: deba@2502: while ((c = is.get()) != EOF) { deba@2502: if (c == '\n') ++line_num; deba@2502: deba@2502: switch (skip_state) { deba@2502: case skip: deba@2502: if (c == '\n') skip_state = after_endl; deba@2502: break; deba@2502: case after_endl: deba@2502: switch (c) { deba@2502: case '@': deba@2502: is.putback(c); deba@2502: return; deba@2502: case '\n': deba@2502: continue; deba@2502: default: deba@2502: if (!isspace(c)) { deba@2502: skip_state = skip; deba@2502: } deba@2502: break; deba@2502: } deba@2502: } deba@2502: } deba@2502: } deba@2502: deba@1408: public: deba@1408: deba@1409: /// \brief Abstract base class for reading a section. deba@1409: /// deba@1409: /// This class has an \c header() member function what get a deba@1409: /// header line string and decides if it want to process the next deba@1409: /// section. Several SectionReaders can be attached to an LemonReader deba@1409: /// and the first attached what can process the section will be used. deba@1409: /// Its \c read() member will called with a stream contains the section. deba@1409: /// From this stream the empty lines and comments are filtered out. deba@1408: class SectionReader { deba@1409: friend class LemonReader; deba@1409: protected: deba@1409: /// \brief Constructor for SectionReader. deba@1409: /// deba@1409: /// Constructor for SectionReader. It attach this reader to deba@1409: /// the given LemonReader. deba@1409: SectionReader(LemonReader& reader) { deba@1409: reader.attach(*this); deba@1409: } deba@1409: alpar@1494: virtual ~SectionReader() {} alpar@1494: deba@1409: /// \brief Gives back true when the SectionReader can process deba@1409: /// the section with the given header line. deba@1409: /// deba@1409: /// It gives back true when the SectionReader can process deba@1409: /// the section with the given header line. deba@1408: virtual bool header(const std::string& line) = 0; deba@1409: deba@1409: /// \brief Reader function of the section. deba@1409: /// deba@1409: /// It reads the content of the section. deba@1408: virtual void read(std::istream& is) = 0; deba@2000: deba@2000: /// \brief The given section missing in the file. deba@2000: /// deba@2000: /// The given section missing in the file. deba@2000: virtual void missing() {}; deba@1408: }; deba@1408: deba@1409: /// \brief Constructor for LemonReader. deba@1409: /// deba@1409: /// Constructor for LemonReader which reads from the given stream. deba@1408: LemonReader(std::istream& _is) deba@1408: : is(&_is), own_is(false) {} deba@1408: deba@1409: /// \brief Constructor for LemonReader. deba@1409: /// deba@1409: /// Constructor for LemonReader which reads from the given file. deba@1408: LemonReader(const std::string& filename) deba@1408: : is(0), own_is(true) { deba@1408: is = new std::ifstream(filename.c_str()); deba@1746: if (is->fail()) { deba@1746: throw FileOpenError(filename); deba@1746: } deba@1408: } deba@1408: deba@1409: /// \brief Desctructor for LemonReader. deba@1409: /// deba@1409: /// Desctructor for LemonReader. deba@1408: ~LemonReader() { deba@1408: if (own_is) { deba@1408: delete is; deba@1408: } deba@1408: } deba@1408: deba@1408: private: deba@1408: LemonReader(const LemonReader&); deba@1408: void operator=(const LemonReader&); deba@1408: deba@1408: void attach(SectionReader& reader) { deba@2000: readers.push_back(std::make_pair(&reader, false)); deba@1408: } deba@1408: deba@1409: public: deba@1409: /// \brief Executes the LemonReader. deba@1409: /// deba@1409: /// It executes the LemonReader. deba@1408: void run() { deba@1408: int line_num = 0; deba@1408: std::string line; deba@2460: deba@2460: SectionReaders::iterator it; deba@2502: skipPreSection(*is, line_num); deba@2460: while ((++line_num, getline(*is, line)) && line.find("@end") != 0) { deba@2460: for (it = readers.begin(); it != readers.end(); ++it) { deba@2460: if (it->first->header(line)) { deba@2460: it->second = true; deba@2460: char buf[2048]; deba@2460: FilterStreamBuf buffer(*is, line_num); deba@2460: try { deba@1408: buffer.pubsetbuf(buf, sizeof(buf)); deba@2386: std::istream ss(&buffer); deba@2386: it->first->read(ss); deba@2502: skipPreSection(*is, line_num); deba@1408: break; deba@2460: } catch (DataFormatError& error) { deba@2460: error.line(buffer.line_num()); deba@2460: throw; deba@2460: } deba@1408: } deba@1408: } deba@2460: } deba@2460: for (it = readers.begin(); it != readers.end(); ++it) { deba@2460: if (!it->second) { deba@2460: try { deba@2460: it->first->missing(); deba@2460: } catch (DataFormatError& error) { deba@2460: error.line(line_num); deba@2460: throw; deba@2460: } deba@2460: } deba@2460: } deba@1408: } deba@1408: deba@1408: deba@1408: private: deba@1408: deba@1408: std::istream* is; deba@1408: bool own_is; deba@1408: deba@2000: typedef std::vector > SectionReaders; deba@1408: SectionReaders readers; deba@1408: deba@1408: }; deba@1408: deba@2016: /// \ingroup section_io deba@1409: /// \brief SectionReader for reading a graph's nodeset. deba@1409: /// deba@2368: /// The lemon format can store multiple graph nodesets with several deba@2368: /// maps. The nodeset section's header line is \c \@nodeset \c deba@2368: /// nodeset_name, but the \c nodeset_name may be empty. deba@1409: /// deba@1409: /// The first line of the section contains the names of the maps separated deba@1409: /// with white spaces. Each next lines describes a node in the nodeset, and deba@1409: /// contains the mapped values for each map. deba@1409: /// deba@1901: /// If the nodeset contains an \c "label" named map then it will be regarded deba@1409: /// as id map. This map should contain only unique values and when the deba@1901: /// \c readLabel() member will read a value from the given stream it will deba@1409: /// give back that node which is mapped to this value. deba@1409: /// deba@1409: /// \relates LemonReader deba@1408: template deba@1845: class NodeSetReader : public LemonReader::SectionReader { deba@1845: typedef LemonReader::SectionReader Parent; deba@1408: public: deba@1408: deba@1408: typedef _Graph Graph; deba@1408: typedef _Traits Traits; deba@1429: typedef typename Graph::Node Node; deba@1408: typedef typename Traits::Skipper DefaultSkipper; deba@1408: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for NodeSetReader. It creates the NodeSetReader and deba@1409: /// attach it into the given LemonReader. The nodeset reader will deba@2100: /// add the read nodes to the given Graph. The reader will read deba@1901: /// the section when the \c section_name and the \c _name are the same. deba@1421: NodeSetReader(LemonReader& _reader, deba@1705: Graph& _graph, deba@1901: const std::string& _name = std::string(), deba@1409: const DefaultSkipper& _skipper = DefaultSkipper()) deba@1901: : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} deba@1408: deba@1409: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for NodeSetReader. deba@1408: virtual ~NodeSetReader() { deba@1408: for (typename MapReaders::iterator it = readers.begin(); deba@1408: it != readers.end(); ++it) { deba@1408: delete it->second; deba@1408: } deba@1408: } deba@1408: deba@1408: private: deba@1408: NodeSetReader(const NodeSetReader&); deba@1408: void operator=(const NodeSetReader&); deba@1408: deba@1408: public: deba@1408: deba@1408: /// \brief Add a new node map reader command for the reader. deba@1408: /// deba@1408: /// Add a new node map reader command for the reader. deba@1408: template deba@2386: NodeSetReader& readNodeMap(std::string label, Map& map) { deba@1421: return _readMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1421: } deba@1421: deba@1421: template deba@2386: NodeSetReader& readNodeMap(std::string label, const Map& map) { deba@1421: return _readMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1408: } deba@1408: deba@1408: /// \brief Add a new node map reader command for the reader. deba@1408: /// deba@1408: /// Add a new node map reader command for the reader. deba@2386: template deba@2386: NodeSetReader& readNodeMap(std::string label, Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readMap::Type> deba@2386: (label, map, ir); deba@1421: } deba@1421: deba@2386: template deba@2386: NodeSetReader& readNodeMap(std::string label, const Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readMap::Type> deba@2386: (label, map, ir); deba@1421: } deba@1421: deba@1421: private: deba@1421: deba@2386: template deba@2386: NodeSetReader& _readMap(std::string label, MapParameter map, deba@2386: const ItemReader& ir = ItemReader()) { alpar@2260: checkConcept, Map>(); deba@2386: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2386: if (readers.find(label) != readers.end()) { deba@1408: ErrorMessage msg; deba@2386: msg << "Multiple read rule for node map: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1845: } deba@1408: readers.insert( deba@2386: make_pair(label, new _reader_bits:: deba@2386: MapReader(map, ir))); deba@1408: return *this; deba@1408: } deba@1408: deba@1421: public: deba@1421: deba@1408: /// \brief Add a new node map skipper command for the reader. deba@1408: /// deba@1408: /// Add a new node map skipper command for the reader. deba@2386: template deba@2386: NodeSetReader& skipNodeMap(std::string label, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: if (readers.find(label) != readers.end()) { deba@1408: ErrorMessage msg; deba@2386: msg << "Multiple read rule for node map: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1408: } deba@2386: readers.insert(make_pair(label, new _reader_bits:: deba@2386: SkipReader(ir))); deba@1408: return *this; deba@1408: } deba@1408: deba@1409: protected: deba@1409: deba@1409: /// \brief Gives back true when the SectionReader can process deba@1409: /// the section with the given header line. deba@1409: /// deba@1421: /// It gives back true when the header line starts with \c \@nodeset, deba@1901: /// and the header line's name and the nodeset's name are the same. deba@1408: virtual bool header(const std::string& line) { deba@1408: std::istringstream ls(line); deba@1408: std::string command; deba@1901: std::string id; klao@1997: ls >> command >> id; deba@1408: return command == "@nodeset" && name == id; deba@1408: } deba@1408: deba@1409: /// \brief Reader function of the section. deba@1409: /// deba@1409: /// It reads the content of the section. deba@1408: virtual void read(std::istream& is) { deba@1845: std::vector<_reader_bits::MapReaderBase* > index; deba@1408: std::string line; deba@1408: deba@2386: { deba@2386: getline(is, line); deba@2386: std::istringstream ls(line); deba@2386: std::string id; deba@2386: while (ls >> id) { deba@2386: typename MapReaders::iterator it = readers.find(id); deba@2386: if (it != readers.end()) { deba@2386: it->second->touch(); deba@2386: index.push_back(it->second); deba@2386: } else { deba@2386: index.push_back(&skipper); deba@2386: } deba@2386: if (id == "label") { deba@2386: inverter.reset(index.back()->getInverter()); deba@2386: index.back() = inverter.get(); deba@2386: } deba@2386: } deba@1408: } deba@1845: for (typename MapReaders::iterator it = readers.begin(); deba@1845: it != readers.end(); ++it) { deba@1845: if (!it->second->touched()) { deba@1845: ErrorMessage msg; deba@1845: msg << "Map not found in file: " << it->first; alpar@2153: throw IoParameterError(msg.message()); deba@1845: } deba@1845: } deba@1408: while (getline(is, line)) { deba@1429: Node node = graph.addNode(); deba@1408: std::istringstream ls(line); deba@2386: for (int i = 0; i < int(index.size()); ++i) { deba@1408: index[i]->read(ls, node); deba@1408: } deba@1408: } deba@1408: } deba@1408: deba@2000: virtual void missing() { deba@2000: if (readers.empty()) return; deba@2000: ErrorMessage msg; deba@2001: msg << "NodeSet section not found in file: @nodeset " << name; alpar@2153: throw IoParameterError(msg.message()); deba@2000: } deba@2000: deba@1409: public: deba@1409: deba@1901: /// \brief Returns true if the nodeset can give back the node by its label. deba@1409: /// deba@1901: /// Returns true if the nodeset can give back the node by its label. deba@1901: /// It is possible only if an "label" named map was read. deba@1901: bool isLabelReader() const { deba@1408: return inverter.get() != 0; deba@1408: } deba@1408: deba@1901: /// \brief Gives back the node by its label. deba@1409: /// deba@1409: /// It reads an id from the stream and gives back which node belongs to deba@1901: /// it. It is possible only if there was read an "label" named map. deba@1901: void readLabel(std::istream& is, Node& node) const { deba@1492: node = inverter->read(is); deba@1408: } deba@1408: deba@1408: private: deba@1408: deba@1845: typedef std::map*> MapReaders; deba@1408: MapReaders readers; deba@1408: deba@1705: Graph& graph; deba@1901: std::string name; deba@1845: _reader_bits::SkipReader skipper; deba@1408: deba@1845: std::auto_ptr<_reader_bits::MapInverterBase > inverter; deba@1408: }; deba@1408: deba@2016: /// \ingroup section_io deba@2502: /// \brief SectionReader for reading a bipartite graph's nodeset. deba@2502: /// deba@2502: /// The lemon format can store multiple bipartite graph nodesets deba@2502: /// with several maps. The bipartite graph nodeset section's header deba@2502: /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name deba@2502: /// may be empty. deba@2502: /// deba@2502: /// The first line of the section contains \c "&anodeset" and the deba@2502: /// the names of the A-node maps and regular maps separated with deba@2502: /// white spaces. Each next lines describes an A-node in the anodeset, deba@2502: /// and contains the mapped values for each map. If one of the line deba@2502: /// starts with \c "&bnodeset" then this line contains the names of deba@2502: /// the B-node maps and the regular node maps. And the remaining lines deba@2502: /// contains the mapped values to the B-nodes. deba@2502: /// deba@2502: /// If there is "label" named map then it should be defined in both deba@2502: /// nodeset, and it will be regarded as id map. This map should deba@2502: /// contain only unique values and when the \c readLabel() member deba@2502: /// will read a value from the given stream it will give back that deba@2502: /// node which is mapped to this value. deba@2502: /// deba@2502: /// \relates LemonReader deba@2502: template deba@2502: class BpNodeSetReader : public LemonReader::SectionReader { deba@2502: typedef LemonReader::SectionReader Parent; deba@2502: public: deba@2502: deba@2502: typedef _Graph Graph; deba@2502: typedef _Traits Traits; deba@2502: typedef typename Graph::Node Node; deba@2502: typedef typename Traits::Skipper DefaultSkipper; deba@2502: deba@2502: /// \brief Constructor. deba@2502: /// deba@2502: /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and deba@2502: /// attach it into the given LemonReader. The nodeset reader will deba@2502: /// add the read nodes to the given Graph. The reader will read deba@2502: /// the section when the \c section_name and the \c _name are the same. deba@2502: BpNodeSetReader(LemonReader& _reader, deba@2502: Graph& _graph, deba@2502: const std::string& _name = std::string(), deba@2502: const DefaultSkipper& _skipper = DefaultSkipper()) deba@2502: : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} deba@2502: deba@2502: deba@2502: /// \brief Destructor. deba@2502: /// deba@2502: /// Destructor for BpNodeSetReader. deba@2502: virtual ~BpNodeSetReader() { deba@2502: for (typename MapReaders::iterator it = readers.begin(); deba@2502: it != readers.end(); ++it) { deba@2502: delete it->second; deba@2502: } deba@2502: } deba@2502: deba@2502: private: deba@2502: BpNodeSetReader(const BpNodeSetReader&); deba@2502: void operator=(const BpNodeSetReader&); deba@2502: deba@2502: public: deba@2502: deba@2502: /// \brief Add a new node map reader command for the reader. deba@2502: /// deba@2502: /// Add a new node map reader command for the reader. deba@2502: template deba@2502: BpNodeSetReader& readNodeMap(std::string label, Map& map) { deba@2502: return _readMap< deba@2502: typename Traits::template Reader, Map, deba@2502: typename _reader_bits::Arg::Type>(label, map); deba@2502: } deba@2502: deba@2502: template deba@2502: BpNodeSetReader& readNodeMap(std::string label, const Map& map) { deba@2502: return _readMap< deba@2502: typename Traits::template Reader, Map, deba@2502: typename _reader_bits::Arg::Type>(label, map); deba@2502: } deba@2502: deba@2502: /// \brief Add a new node map reader command for the reader. deba@2502: /// deba@2502: /// Add a new node map reader command for the reader. deba@2502: template deba@2502: BpNodeSetReader& readNodeMap(std::string label, Map& map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: return _readMap::Type> deba@2502: (label, map, ir); deba@2502: } deba@2502: deba@2502: template deba@2502: BpNodeSetReader& readNodeMap(std::string label, const Map& map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: return _readMap::Type> deba@2502: (label, map, ir); deba@2502: } deba@2502: deba@2502: private: deba@2502: deba@2502: template deba@2502: BpNodeSetReader& _readMap(std::string label, MapParameter map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: checkConcept, Map>(); deba@2502: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2502: if (areaders.find(label) != areaders.end() || deba@2502: breaders.find(label) != breaders.end() || deba@2502: readers.find(label) != readers.end()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Multiple read rule for node map: " << label; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: readers.insert(make_pair(label, new _reader_bits:: deba@2502: MapReader(map, ir))); deba@2502: return *this; deba@2502: } deba@2502: deba@2502: public: deba@2502: deba@2502: /// \brief Add a new A-node map reader command for the reader. deba@2502: /// deba@2502: /// Add a new A-node map reader command for the reader. deba@2502: template deba@2502: BpNodeSetReader& readANodeMap(std::string label, Map& map) { deba@2502: return _readAMap< deba@2502: typename Traits::template Reader, Map, deba@2502: typename _reader_bits::Arg::Type>(label, map); deba@2502: } deba@2502: deba@2502: template deba@2502: BpNodeSetReader& readANodeMap(std::string label, const Map& map) { deba@2502: return _readAMap< deba@2502: typename Traits::template Reader, Map, deba@2502: typename _reader_bits::Arg::Type>(label, map); deba@2502: } deba@2502: deba@2502: /// \brief Add a new A-node map reader command for the reader. deba@2502: /// deba@2502: /// Add a new A-node map reader command for the reader. deba@2502: template deba@2502: BpNodeSetReader& readANodeMap(std::string label, Map& map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: return _readAMap::Type> deba@2502: (label, map, ir); deba@2502: } deba@2502: deba@2502: template deba@2502: BpNodeSetReader& readANodeMap(std::string label, const Map& map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: return _readAMap::Type> deba@2502: (label, map, ir); deba@2502: } deba@2502: deba@2502: private: deba@2502: deba@2502: template deba@2502: BpNodeSetReader& _readAMap(std::string label, MapParameter map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: checkConcept, Map>(); deba@2502: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2502: if (label == "label") { deba@2502: throw IoParameterError("Label cannot be A-node map"); deba@2502: } deba@2502: if (areaders.find(label) != areaders.end() || deba@2502: readers.find(label) != readers.end()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Multiple read rule for A-node map: " << label; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: areaders.insert(make_pair(label, new _reader_bits:: deba@2502: MapReader(map, ir))); deba@2502: return *this; deba@2502: } deba@2502: deba@2502: public: deba@2502: deba@2502: /// \brief Add a new B-node map reader command for the reader. deba@2502: /// deba@2502: /// Add a new B-node map reader command for the reader. deba@2502: template deba@2502: BpNodeSetReader& readBNodeMap(std::string label, Map& map) { deba@2502: return _readBMap< deba@2502: typename Traits::template Reader, Map, deba@2502: typename _reader_bits::Arg::Type>(label, map); deba@2502: } deba@2502: deba@2502: template deba@2502: BpNodeSetReader& readBNodeMap(std::string label, const Map& map) { deba@2502: return _readBMap< deba@2502: typename Traits::template Reader, Map, deba@2502: typename _reader_bits::Arg::Type>(label, map); deba@2502: } deba@2502: deba@2502: /// \brief Add a new B-node map reader command for the reader. deba@2502: /// deba@2502: /// Add a new B-node map reader command for the reader. deba@2502: template deba@2502: BpNodeSetReader& readBNodeMap(std::string label, Map& map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: return _readBMap::Type> deba@2502: (label, map, ir); deba@2502: } deba@2502: deba@2502: template deba@2502: BpNodeSetReader& readBNodeMap(std::string label, const Map& map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: return _readBMap::Type> deba@2502: (label, map, ir); deba@2502: } deba@2502: deba@2502: private: deba@2502: deba@2502: template deba@2502: BpNodeSetReader& _readBMap(std::string label, MapParameter map, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: checkConcept, Map>(); deba@2502: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2502: if (label == "label") { deba@2502: throw IoParameterError("Label cannot be B-node map"); deba@2502: } deba@2502: if (breaders.find(label) != breaders.end() || deba@2502: readers.find(label) != readers.end()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Multiple read rule for B-node map: " << label; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: breaders.insert(make_pair(label, new _reader_bits:: deba@2502: MapReader(map, ir))); deba@2502: return *this; deba@2502: } deba@2502: deba@2502: public: deba@2502: deba@2502: /// \brief Add a new node map skipper command for the reader. deba@2502: /// deba@2502: /// Add a new node map skipper command for the reader. deba@2502: template deba@2502: BpNodeSetReader& skipNodeMap(std::string label, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: if (areaders.find(label) != areaders.end() || deba@2502: breaders.find(label) != breaders.end() || deba@2502: readers.find(label) != readers.end()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Multiple read rule for node map: " << label; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: readers.insert(make_pair(label, new _reader_bits:: deba@2502: SkipReader(ir))); deba@2502: return *this; deba@2502: } deba@2502: deba@2502: /// \brief Add a new A-node map skipper command for the reader. deba@2502: /// deba@2502: /// Add a new A-node map skipper command for the reader. deba@2502: template deba@2502: BpNodeSetReader& skipANodeMap(std::string label, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: if (label == "label") { deba@2502: throw IoParameterError("Label cannot be A-node map"); deba@2502: } deba@2502: if (areaders.find(label) != areaders.end() || deba@2502: readers.find(label) != readers.end()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Multiple read rule for A-node map: " << label; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: areaders.insert(make_pair(label, new _reader_bits:: deba@2502: SkipReader(ir))); deba@2502: return *this; deba@2502: } deba@2502: deba@2502: /// \brief Add a new B-node map skipper command for the reader. deba@2502: /// deba@2502: /// Add a new B-node map skipper command for the reader. deba@2502: template deba@2502: BpNodeSetReader& skipBNodeMap(std::string label, deba@2502: const ItemReader& ir = ItemReader()) { deba@2502: if (label == "label") { deba@2502: throw IoParameterError("Label cannot be B-node map"); deba@2502: } deba@2502: if (breaders.find(label) != breaders.end() || deba@2502: readers.find(label) != readers.end()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Multiple read rule for B-node map: " << label; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: breaders.insert(make_pair(label, new _reader_bits:: deba@2502: SkipReader(ir))); deba@2502: return *this; deba@2502: } deba@2502: deba@2502: deba@2502: protected: deba@2502: deba@2502: /// \brief Gives back true when the SectionReader can process deba@2502: /// the section with the given header line. deba@2502: /// deba@2502: /// It gives back true when the header line starts with \c \@nodeset, deba@2502: /// and the header line's name and the nodeset's name are the same. deba@2502: virtual bool header(const std::string& line) { deba@2502: std::istringstream ls(line); deba@2502: std::string command; deba@2502: std::string id; deba@2502: ls >> command >> id; deba@2502: return command == "@bpnodeset" && name == id; deba@2502: } deba@2502: deba@2502: /// \brief Reader function of the section. deba@2502: /// deba@2502: /// It reads the content of the section. deba@2502: virtual void read(std::istream& is) { deba@2502: std::string line; deba@2502: { deba@2502: std::vector<_reader_bits::MapReaderBase* > index; deba@2502: { deba@2502: getline(is, line); deba@2502: std::istringstream ls(line); deba@2502: std::string id; deba@2502: ls >> id; deba@2502: if (id != "&anodeset") { deba@2502: throw IoParameterError("Cannot find &anodeset subsection"); deba@2502: } deba@2502: while (ls >> id) { deba@2502: typename MapReaders::iterator it = readers.find(id); deba@2502: typename MapReaders::iterator ait = areaders.find(id); deba@2502: if (it != readers.end()) { deba@2502: it->second->touch(); deba@2502: index.push_back(it->second); deba@2502: } else if (ait != areaders.end()) { deba@2502: ait->second->touch(); deba@2502: index.push_back(ait->second); deba@2504: } else { deba@2504: index.push_back(&skipper); deba@2502: } deba@2502: if (id == "label") { deba@2502: inverter.reset(index.back()->getInverter()); deba@2502: index.back() = inverter.get(); deba@2502: } deba@2502: } deba@2502: } deba@2502: for (typename MapReaders::iterator it = areaders.begin(); deba@2502: it != areaders.end(); ++it) { deba@2502: if (!it->second->touched()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Map not found in file: " << it->first; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: } deba@2502: for (typename MapReaders::iterator it = readers.begin(); deba@2502: it != readers.end(); ++it) { deba@2502: if (!it->second->touched()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Map not found in file: " << it->first; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: it->second->touch(false); deba@2502: } deba@2502: deba@2502: while (getline(is, line)) { deba@2502: if (line[0] == '&') { deba@2502: std::istringstream ls(line); deba@2502: std::string id; deba@2502: ls >> id; deba@2502: if (id == "&bnodeset") break; deba@2502: } deba@2502: Node node = graph.addANode(); deba@2502: std::istringstream ls(line); deba@2502: for (int i = 0; i < int(index.size()); ++i) { deba@2502: index[i]->read(ls, node); deba@2502: } deba@2502: } deba@2502: } deba@2502: deba@2502: { deba@2502: std::vector<_reader_bits::MapReaderBase* > index; deba@2502: { deba@2502: std::istringstream ls(line); deba@2502: std::string id; deba@2502: ls >> id; deba@2502: if (id != "&bnodeset") { deba@2502: throw IoParameterError("Cannot find &bnodeset subsection"); deba@2502: } deba@2502: while (ls >> id) { deba@2502: typename MapReaders::iterator it = readers.find(id); deba@2502: typename MapReaders::iterator bit = breaders.find(id); deba@2502: if (it != readers.end()) { deba@2502: it->second->touch(); deba@2502: index.push_back(it->second); deba@2502: } else if (bit != breaders.end()) { deba@2502: bit->second->touch(); deba@2502: index.push_back(bit->second); deba@2504: } else { deba@2504: index.push_back(&skipper); deba@2502: } deba@2502: if (id == "label" && inverter.get() != 0) { deba@2502: index.back() = inverter.get(); deba@2502: } deba@2502: } deba@2502: } deba@2502: for (typename MapReaders::iterator it = breaders.begin(); deba@2502: it != breaders.end(); ++it) { deba@2502: if (!it->second->touched()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Map not found in file: " << it->first; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: } deba@2502: for (typename MapReaders::iterator it = readers.begin(); deba@2502: it != readers.end(); ++it) { deba@2502: if (!it->second->touched()) { deba@2502: ErrorMessage msg; deba@2502: msg << "Map not found in file: " << it->first; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: } deba@2502: while (getline(is, line)) { deba@2502: Node node = graph.addBNode(); deba@2502: std::istringstream ls(line); deba@2502: for (int i = 0; i < int(index.size()); ++i) { deba@2502: index[i]->read(ls, node); deba@2502: } deba@2502: } deba@2502: } deba@2502: } deba@2502: deba@2502: virtual void missing() { deba@2502: if (readers.empty()) return; deba@2502: ErrorMessage msg; deba@2502: msg << "BpNodeSet section not found in file: @bpnodeset " << name; deba@2502: throw IoParameterError(msg.message()); deba@2502: } deba@2502: deba@2502: public: deba@2502: deba@2502: /// \brief Returns true if the nodeset can give back the node by its label. deba@2502: /// deba@2502: /// Returns true if the nodeset can give back the node by its label. deba@2502: /// It is possible only if an "label" named map was read. deba@2502: bool isLabelReader() const { deba@2502: return inverter.get() != 0; deba@2502: } deba@2502: deba@2502: /// \brief Gives back the node by its label. deba@2502: /// deba@2502: /// It reads an id from the stream and gives back which node belongs to deba@2502: /// it. It is possible only if there was read an "label" named map. deba@2502: void readLabel(std::istream& is, Node& node) const { deba@2502: node = inverter->read(is); deba@2502: } deba@2502: deba@2502: private: deba@2502: deba@2502: typedef std::map*> deba@2502: MapReaders; deba@2502: deba@2502: MapReaders areaders, breaders, readers; deba@2502: deba@2502: Graph& graph; deba@2502: std::string name; deba@2502: _reader_bits::SkipReader skipper; deba@2502: deba@2502: std::auto_ptr<_reader_bits::MapInverterBase > inverter; deba@2502: }; deba@2502: deba@2502: deba@2502: /// \ingroup section_io deba@1409: /// \brief SectionReader for reading a graph's edgeset. deba@1409: /// deba@1409: /// The lemon format can store multiple graph edgesets with several maps. deba@1901: /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the deba@1901: /// \c edgeset_name may be empty. deba@1409: /// deba@1409: /// The first line of the section contains the names of the maps separated deba@1421: /// with white spaces. Each next lines describes an edge in the edgeset. The deba@1421: /// line contains the source and the target nodes' id and the mapped deba@1421: /// values for each map. deba@1409: /// deba@1901: /// If the edgeset contains an \c "label" named map then it will be regarded deba@1409: /// as id map. This map should contain only unique values and when the deba@1901: /// \c readLabel() member will read a value from the given stream it will deba@1409: /// give back that edge which is mapped to this value. deba@1409: /// deba@1409: /// The edgeset reader needs a node id reader to identify which nodes deba@1901: /// have to be connected. If a NodeSetReader reads an "label" named map, deba@1409: /// it will be able to resolve the nodes by ids. deba@1409: /// deba@1409: /// \relates LemonReader deba@1408: template deba@1845: class EdgeSetReader : public LemonReader::SectionReader { deba@1845: typedef LemonReader::SectionReader Parent; deba@1408: public: deba@1408: deba@1408: typedef _Graph Graph; deba@1408: typedef _Traits Traits; deba@1429: typedef typename Graph::Node Node; deba@1429: typedef typename Graph::Edge Edge; deba@1408: typedef typename Traits::Skipper DefaultSkipper; deba@1408: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for EdgeSetReader. It creates the EdgeSetReader and deba@1409: /// attach it into the given LemonReader. The edgeset reader will deba@2100: /// add the read edges to the given Graph. It will use the given deba@1409: /// node id reader to read the source and target nodes of the edges. deba@1901: /// The reader will read the section only if the \c _name and the deba@1901: /// \c edgset_name are the same. deba@1901: template deba@1421: EdgeSetReader(LemonReader& _reader, deba@1705: Graph& _graph, deba@1901: const NodeLabelReader& _nodeLabelReader, deba@1901: const std::string& _name = std::string(), deba@1409: const DefaultSkipper& _skipper = DefaultSkipper()) deba@1901: : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { deba@1901: checkConcept<_reader_bits::ItemLabelReader, NodeLabelReader>(); deba@1901: nodeLabelReader.reset(new _reader_bits:: deba@1901: LabelReader(_nodeLabelReader)); deba@1476: } deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for EdgeSetReader. deba@1408: virtual ~EdgeSetReader() { deba@1408: for (typename MapReaders::iterator it = readers.begin(); deba@1408: it != readers.end(); ++it) { deba@1408: delete it->second; deba@1408: } deba@1408: } deba@1408: deba@1408: private: deba@1408: EdgeSetReader(const EdgeSetReader&); deba@1408: void operator=(const EdgeSetReader&); deba@1408: deba@1408: public: deba@1408: deba@1409: /// \brief Add a new edge map reader command for the reader. deba@1408: /// deba@1409: /// Add a new edge map reader command for the reader. deba@1408: template deba@2386: EdgeSetReader& readEdgeMap(std::string label, Map& map) { deba@1421: return _readMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1421: } deba@1421: deba@1421: template deba@2386: EdgeSetReader& readEdgeMap(std::string label, const Map& map) { deba@1421: return _readMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1408: } deba@1408: deba@1409: /// \brief Add a new edge map reader command for the reader. deba@1408: /// deba@1409: /// Add a new edge map reader command for the reader. deba@2386: template deba@2386: EdgeSetReader& readEdgeMap(std::string label, Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readMap::Type>(label, map, ir); deba@1421: } deba@1421: deba@2386: template deba@2386: EdgeSetReader& readEdgeMap(std::string label, const Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readMap::Type>(label, map, ir); deba@1421: } deba@1421: deba@1421: private: deba@1421: deba@2386: template deba@2386: EdgeSetReader& _readMap(std::string label, MapParameter map, deba@2386: const ItemReader& ir = ItemReader()) { alpar@2260: checkConcept, Map>(); deba@2386: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2386: if (readers.find(label) != readers.end()) { deba@1408: ErrorMessage msg; deba@2386: msg << "Multiple read rule for edge map: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1408: } deba@1408: readers.insert( deba@2386: make_pair(label, new _reader_bits:: deba@2386: MapReader(map, ir))); deba@1408: return *this; deba@1408: } deba@1408: deba@1421: public: deba@1421: deba@1409: /// \brief Add a new edge map skipper command for the reader. deba@1408: /// deba@1409: /// Add a new edge map skipper command for the reader. deba@2386: template deba@2386: EdgeSetReader& skipEdgeMap(std::string label, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: if (readers.find(label) != readers.end()) { deba@1408: ErrorMessage msg; deba@2386: msg << "Multiple read rule for edge map: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1408: } deba@2386: readers.insert(make_pair(label, new _reader_bits:: deba@2386: SkipReader(ir))); deba@1408: return *this; deba@1408: } deba@1408: deba@1409: protected: deba@1409: deba@1409: /// \brief Gives back true when the SectionReader can process deba@1409: /// the section with the given header line. deba@1409: /// deba@1421: /// It gives back true when the header line starts with \c \@edgeset, deba@1901: /// and the header line's name and the edgeset's name are the same. kpeter@2476: /// The sections with \@uedgeset head line could be read with this deba@2464: /// section reader too. deba@1408: virtual bool header(const std::string& line) { deba@1408: std::istringstream ls(line); deba@1408: std::string command; deba@1901: std::string id; klao@1997: ls >> command >> id; deba@2464: return (command == "@edgeset" || command == "@uedgeset") && name == id; deba@1408: } deba@1408: deba@1409: /// \brief Reader function of the section. deba@1409: /// deba@1409: /// It reads the content of the section. deba@1408: virtual void read(std::istream& is) { deba@1901: if (!nodeLabelReader->isLabelReader()) { deba@1901: throw DataFormatError("Cannot find nodeset or label map"); deba@1476: } deba@1845: std::vector<_reader_bits::MapReaderBase* > index; deba@1408: std::string line; deba@1408: deba@2386: { deba@2386: getline(is, line); deba@2386: std::istringstream ls(line); deba@2386: std::string id; deba@2386: while (ls >> id) { deba@2386: typename MapReaders::iterator it = readers.find(id); deba@2386: if (it != readers.end()) { deba@2386: index.push_back(it->second); deba@2386: it->second->touch(); deba@2386: } else { deba@2386: index.push_back(&skipper); deba@2386: } deba@2386: if (id == "label") { deba@2386: inverter.reset(index.back()->getInverter()); deba@2386: index.back() = inverter.get(); deba@2386: } deba@2386: } deba@1408: } deba@1845: for (typename MapReaders::iterator it = readers.begin(); deba@1845: it != readers.end(); ++it) { deba@1845: if (!it->second->touched()) { deba@1845: ErrorMessage msg; deba@1845: msg << "Map not found in file: " << it->first; alpar@2153: throw IoParameterError(msg.message()); deba@1845: } deba@1845: } deba@1408: while (getline(is, line)) { deba@1408: std::istringstream ls(line); deba@1901: Node from = nodeLabelReader->read(ls); deba@1901: Node to = nodeLabelReader->read(ls); deba@1429: Edge edge = graph.addEdge(from, to); deba@2386: for (int i = 0; i < int(index.size()); ++i) { deba@1408: index[i]->read(ls, edge); deba@1408: } deba@1408: } deba@1408: } deba@1408: deba@2000: virtual void missing() { deba@2000: if (readers.empty()) return; deba@2000: ErrorMessage msg; deba@2001: msg << "EdgeSet section not found in file: @edgeset " << name; alpar@2153: throw IoParameterError(msg.message()); deba@2000: } deba@2000: deba@1409: public: deba@1409: deba@1901: /// \brief Returns true if the edgeset can give back the edge by its label. deba@1409: /// deba@1901: /// Returns true if the edgeset can give back the edge by its label. deba@1901: /// It is possible only if an "label" named map was read. deba@1901: bool isLabelReader() const { deba@1408: return inverter.get() != 0; deba@1408: } deba@1408: deba@1901: /// \brief Gives back the edge by its label. deba@1409: /// deba@1409: /// It reads an id from the stream and gives back which edge belongs to deba@1901: /// it. It is possible only if there was read an "label" named map. deba@1901: void readLabel(std::istream& is, Edge& edge) const { deba@1492: edge = inverter->read(is); deba@1408: } deba@1408: deba@1408: private: deba@1408: deba@2001: typedef std::map*> deba@2001: MapReaders; deba@2001: deba@1408: MapReaders readers; deba@1408: deba@1705: Graph& graph; deba@1901: std::string name; deba@1845: _reader_bits::SkipReader skipper; deba@1421: deba@1845: std::auto_ptr<_reader_bits::MapInverterBase > inverter; deba@1901: std::auto_ptr<_reader_bits::LabelReaderBase > nodeLabelReader; deba@1421: }; deba@1421: deba@2016: /// \ingroup section_io deba@1421: /// \brief SectionReader for reading a undirected graph's edgeset. deba@1421: /// deba@1421: /// The lemon format can store multiple undirected edgesets with several klao@1909: /// maps. The undirected edgeset section's header line is \c \@uedgeset klao@1909: /// \c uedgeset_name, but the \c uedgeset_name may be empty. deba@1421: /// deba@1421: /// The first line of the section contains the names of the maps separated deba@1421: /// with white spaces. Each next lines describes an edge in the edgeset. The deba@1421: /// line contains the connected nodes' id and the mapped values for each map. deba@1421: /// deba@1421: /// The section can handle the directed as a syntactical sugar. Two deba@1421: /// undirected edge map describes one directed edge map. This two maps deba@1421: /// are the forward map and the backward map and the names of this map deba@1421: /// is near the same just with a prefix \c '+' or \c '-' character deba@1421: /// difference. deba@1421: /// deba@1901: /// If the edgeset contains an \c "label" named map then it will be regarded deba@1421: /// as id map. This map should contain only unique values and when the deba@1901: /// \c readLabel() member will read a value from the given stream it will klao@1909: /// give back that uicted edge which is mapped to this value. deba@1421: /// deba@1421: /// The undirected edgeset reader needs a node id reader to identify which deba@2001: /// nodes have to be connected. If a NodeSetReader reads an "label" named deba@2001: /// map, it will be able to resolve the nodes by ids. deba@1421: /// deba@1421: /// \relates LemonReader deba@1421: template klao@1909: class UEdgeSetReader : public LemonReader::SectionReader { deba@1845: typedef LemonReader::SectionReader Parent; deba@1421: public: deba@1421: deba@1421: typedef _Graph Graph; deba@1421: typedef _Traits Traits; deba@1429: typedef typename Graph::Node Node; deba@1429: typedef typename Graph::Edge Edge; klao@1909: typedef typename Graph::UEdge UEdge; deba@1421: typedef typename Traits::Skipper DefaultSkipper; deba@1421: deba@1421: /// \brief Constructor. deba@1421: /// klao@1909: /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader deba@1421: /// and attach it into the given LemonReader. The undirected edgeset deba@2100: /// reader will add the read undirected edges to the given Graph. It deba@1421: /// will use the given node id reader to read the source and target deba@1421: /// nodes of the edges. The reader will read the section only if the klao@1909: /// \c _name and the \c uedgset_name are the same. deba@1901: template klao@1909: UEdgeSetReader(LemonReader& _reader, deba@1705: Graph& _graph, deba@1901: const NodeLabelReader& _nodeLabelReader, deba@1901: const std::string& _name = std::string(), deba@1421: const DefaultSkipper& _skipper = DefaultSkipper()) deba@1901: : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { deba@1901: checkConcept<_reader_bits::ItemLabelReader, NodeLabelReader>(); deba@1901: nodeLabelReader.reset(new _reader_bits:: deba@1901: LabelReader(_nodeLabelReader)); deba@1476: } deba@1421: /// \brief Destructor. deba@1421: /// klao@1909: /// Destructor for UEdgeSetReader. klao@1909: virtual ~UEdgeSetReader() { deba@1421: for (typename MapReaders::iterator it = readers.begin(); deba@1421: it != readers.end(); ++it) { deba@1421: delete it->second; deba@1421: } deba@1421: } deba@1421: deba@1421: private: klao@1909: UEdgeSetReader(const UEdgeSetReader&); klao@1909: void operator=(const UEdgeSetReader&); deba@1421: deba@1421: public: deba@1421: deba@1421: /// \brief Add a new undirected edge map reader command for the reader. deba@1421: /// deba@1421: /// Add a new edge undirected map reader command for the reader. deba@1421: template deba@2386: UEdgeSetReader& readUEdgeMap(std::string label, Map& map) { deba@1421: return _readMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1421: } deba@1421: deba@1421: template deba@2386: UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) { deba@1421: return _readMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1421: } deba@1421: deba@1421: /// \brief Add a new undirected edge map reader command for the reader. deba@1421: /// deba@1421: /// Add a new edge undirected map reader command for the reader. deba@2386: template deba@2386: UEdgeSetReader& readUEdgeMap(std::string label, Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readMap::Type> deba@2386: (label, map, ir); deba@1421: } deba@1421: deba@2386: template deba@2386: UEdgeSetReader& readUEdgeMap(std::string label, const Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readMap::Type > deba@2386: (label, map, ir); deba@1421: } deba@1421: deba@1421: private: deba@1421: deba@2386: template deba@2386: UEdgeSetReader& _readMap(std::string label, MapParameter map, deba@2386: const ItemReader& ir = ItemReader()) { alpar@2260: checkConcept, Map>(); deba@2386: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2386: if (readers.find(label) != readers.end()) { deba@1421: ErrorMessage msg; deba@2386: msg << "Multiple read rule for edge map: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1421: } deba@1421: readers.insert( deba@2386: make_pair(label, new _reader_bits:: deba@2386: MapReader(map, ir))); deba@1421: return *this; deba@1421: } deba@1421: deba@1421: public: deba@1421: deba@1421: /// \brief Add a new undirected edge map skipper command for the reader. deba@1421: /// deba@1421: /// Add a new undirected edge map skipper command for the reader. deba@2386: template deba@2386: UEdgeSetReader& skipUEdgeMap(std::string label, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: if (readers.find(label) != readers.end()) { deba@1421: ErrorMessage msg; deba@2386: msg << "Multiple read rule for node map: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1421: } deba@2386: readers.insert(make_pair(label, new _reader_bits:: deba@2386: SkipReader(ir))); deba@1421: return *this; deba@1421: } deba@1421: deba@1421: /// \brief Add a new directed edge map reader command for the reader. deba@1421: /// deba@1421: /// Add a new directed edge map reader command for the reader. deba@1421: template deba@2386: UEdgeSetReader& readEdgeMap(std::string label, Map& map) { deba@1421: return _readDirMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1421: } deba@1421: deba@1421: template deba@2386: UEdgeSetReader& readEdgeMap(std::string label, const Map& map) { deba@1421: return _readDirMap< deba@1421: typename Traits::template Reader, Map, deba@2386: typename _reader_bits::Arg::Type>(label, map); deba@1421: } deba@1421: deba@1421: /// \brief Add a new directed edge map reader command for the reader. deba@1421: /// deba@1421: /// Add a new directed edge map reader command for the reader. deba@2386: template deba@2386: UEdgeSetReader& readEdgeMap(std::string label, Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readDirMap::Type>(label, map, ir); deba@1421: } deba@1421: deba@2386: template deba@2386: UEdgeSetReader& readEdgeMap(std::string label, const Map& map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: return _readDirMap::Type>(label, map, ir); deba@1421: } deba@1421: deba@1421: private: deba@1421: deba@2386: template deba@2386: UEdgeSetReader& _readDirMap(std::string label, MapParameter map, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: checkConcept<_reader_bits::ItemReader, ItemReader>(); alpar@2260: checkConcept, Map>(); deba@2386: readUEdgeMap("+" + label, deba@2386: _reader_bits::forwardComposeMap(graph, map), ir); deba@2386: readUEdgeMap("-" + label, deba@2386: _reader_bits::backwardComposeMap(graph, map), ir); deba@1421: return *this; deba@1421: } deba@1421: deba@1421: public: deba@1421: deba@1421: /// \brief Add a new directed edge map skipper command for the reader. deba@1421: /// deba@1421: /// Add a new directed edge map skipper command for the reader. deba@2386: template deba@2386: UEdgeSetReader& skipEdgeMap(std::string label, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: skipUEdgeMap("+" + label, ir); deba@2386: skipUEdgeMap("-" + label, ir); deba@1421: return *this; deba@1421: } deba@1421: deba@1421: protected: deba@1421: deba@1421: /// \brief Gives back true when the SectionReader can process deba@1421: /// the section with the given header line. deba@1421: /// klao@1909: /// It gives back true when the header line starts with \c \@uedgeset, deba@1901: /// and the header line's name and the edgeset's name are the same. kpeter@2476: /// The sections with \@edgeset head line could be read with this deba@2464: /// section reader too. deba@1421: virtual bool header(const std::string& line) { deba@1421: std::istringstream ls(line); deba@1421: std::string command; deba@1901: std::string id; klao@1997: ls >> command >> id; deba@2464: return (command == "@edgeset" || command == "@uedgeset") && name == id; deba@1421: } deba@1421: deba@1421: /// \brief Reader function of the section. deba@1421: /// deba@1421: /// It reads the content of the section. deba@1421: virtual void read(std::istream& is) { deba@1901: if (!nodeLabelReader->isLabelReader()) { deba@1901: throw DataFormatError("Cannot find nodeset or label map"); deba@1476: } klao@1909: std::vector<_reader_bits::MapReaderBase* > index; deba@1421: std::string line; deba@1421: deba@2386: { deba@2386: getline(is, line); deba@2386: std::istringstream ls(line); deba@2386: std::string id; deba@2386: while (ls >> id) { deba@2386: typename MapReaders::iterator it = readers.find(id); deba@2386: if (it != readers.end()) { deba@2386: index.push_back(it->second); deba@2386: it->second->touch(); deba@2386: } else { deba@2386: index.push_back(&skipper); deba@2386: } deba@2386: if (id == "label") { deba@2386: inverter.reset(index.back()->getInverter()); deba@2386: index.back() = inverter.get(); deba@2386: } deba@2386: } deba@2386: for (typename MapReaders::iterator it = readers.begin(); deba@2386: it != readers.end(); ++it) { deba@2386: if (!it->second->touched()) { deba@2386: ErrorMessage msg; deba@2386: msg << "Map not found in file: " << it->first; deba@2386: throw IoParameterError(msg.message()); deba@2386: } deba@2386: } deba@1845: } deba@1421: while (getline(is, line)) { deba@1421: std::istringstream ls(line); deba@1901: Node from = nodeLabelReader->read(ls); deba@1901: Node to = nodeLabelReader->read(ls); klao@1909: UEdge edge = graph.addEdge(from, to); deba@2386: for (int i = 0; i < int(index.size()); ++i) { deba@1421: index[i]->read(ls, edge); deba@1421: } deba@1421: } deba@1421: } deba@1421: deba@2000: virtual void missing() { deba@2000: if (readers.empty()) return; deba@2000: ErrorMessage msg; deba@2001: msg << "UEdgeSet section not found in file: @uedgeset " << name; alpar@2153: throw IoParameterError(msg.message()); deba@2000: } deba@2000: deba@1421: public: deba@1421: deba@1901: /// \brief Returns true if the edgeset can give back the edge by its label. deba@1421: /// deba@1421: /// Returns true if the edgeset can give back the undirected edge by its deba@1901: /// id. It is possible only if an "label" named map was read. deba@1901: bool isLabelReader() const { deba@1421: return inverter.get() != 0; deba@1421: } deba@1421: deba@1901: /// \brief Gives back the undirected edge by its label. deba@1421: /// deba@1421: /// It reads an id from the stream and gives back which undirected edge deba@1901: /// belongs to it. It is possible only if there was read an "label" named map. deba@2467: void readLabel(std::istream& is, UEdge& uedge) const { deba@2467: uedge = inverter->read(is); deba@1421: } deba@1421: deba@1901: /// \brief Gives back the directed edge by its label. deba@1429: /// deba@1429: /// It reads an id from the stream and gives back which directed edge deba@1429: /// belongs to it. The directed edge id is the \c '+' or \c '-' character deba@1429: /// and the undirected edge id. It is possible only if there was read deba@1901: /// an "label" named map. deba@1901: void readLabel(std::istream& is, Edge& edge) const { deba@1429: char c; deba@1429: is >> c; deba@2467: UEdge uedge = inverter->read(is); deba@1429: if (c == '+') { deba@2467: edge = graph.direct(uedge, true); deba@1429: } else if (c == '-') { deba@2467: edge = graph.direct(uedge, false); deba@1429: } else { deba@1429: throw DataFormatError("Wrong id format for edge " deba@1429: "in undirected edgeset"); deba@1429: } deba@1429: } deba@1429: deba@1421: private: deba@1421: deba@1845: typedef std::map*> MapReaders; deba@1421: MapReaders readers; deba@1421: deba@1705: Graph& graph; deba@1901: std::string name; klao@1909: _reader_bits::SkipReader skipper; deba@1408: klao@1909: std::auto_ptr<_reader_bits::MapInverterBase > inverter; deba@1901: std::auto_ptr<_reader_bits::LabelReaderBase > nodeLabelReader; deba@1408: }; deba@1408: deba@2016: /// \ingroup section_io deba@1409: /// \brief SectionReader for reading labeled nodes. deba@1409: /// deba@1901: /// The nodes section's header line is \c \@nodes \c nodes_name, but the deba@1901: /// \c nodes_name may be empty. deba@1409: /// deba@1409: /// Each line in the section contains the name of the node deba@1409: /// and then the node id. deba@1409: /// deba@1409: /// \relates LemonReader deba@1409: template deba@1845: class NodeReader : public LemonReader::SectionReader { deba@1845: typedef LemonReader::SectionReader Parent; deba@1409: typedef _Graph Graph; deba@1429: typedef typename Graph::Node Node; deba@1409: public: deba@1409: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for NodeReader. It creates the NodeReader and deba@1409: /// attach it into the given LemonReader. It will use the given deba@1409: /// node id reader to give back the nodes. The reader will read the deba@1901: /// section only if the \c _name and the \c nodes_name are the same. deba@1901: template deba@1901: NodeReader(LemonReader& _reader, const _LabelReader& _labelReader, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_reader), name(_name) { deba@1901: checkConcept<_reader_bits::ItemLabelReader, _LabelReader>(); deba@1901: nodeLabelReader.reset(new _reader_bits:: deba@1901: LabelReader(_labelReader)); deba@1476: } deba@1408: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for NodeReader. deba@1409: virtual ~NodeReader() {} deba@1409: deba@1409: private: deba@1409: NodeReader(const NodeReader&); deba@1409: void operator=(const NodeReader&); deba@1409: deba@1409: public: deba@1409: deba@1409: /// \brief Add a node reader command for the NodeReader. deba@1409: /// deba@1409: /// Add a node reader command for the NodeReader. deba@2386: void readNode(std::string label, Node& item) { deba@2386: if (readers.find(label) != readers.end()) { deba@1409: ErrorMessage msg; deba@2386: msg << "Multiple read rule for node: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1409: } deba@2386: readers.insert(make_pair(label, _reader_bits::ItemStore(item))); deba@1409: } deba@1409: deba@1409: protected: deba@1409: deba@1409: /// \brief Gives back true when the SectionReader can process deba@1409: /// the section with the given header line. deba@1409: /// deba@1421: /// It gives back true when the header line start with \c \@nodes, deba@1901: /// and the header line's name and the reader's name are the same. deba@1409: virtual bool header(const std::string& line) { deba@1409: std::istringstream ls(line); deba@1409: std::string command; deba@1901: std::string id; klao@1997: ls >> command >> id; deba@1409: return command == "@nodes" && name == id; deba@1409: } deba@1409: deba@1409: /// \brief Reader function of the section. deba@1409: /// deba@1409: /// It reads the content of the section. deba@1409: virtual void read(std::istream& is) { deba@1901: if (!nodeLabelReader->isLabelReader()) { deba@1901: throw DataFormatError("Cannot find nodeset or label map"); deba@1476: } deba@1409: std::string line; deba@1409: while (getline(is, line)) { deba@1409: std::istringstream ls(line); deba@1409: std::string id; deba@1409: ls >> id; deba@1429: typename NodeReaders::iterator it = readers.find(id); deba@1409: if (it != readers.end()) { deba@1901: it->second.read(nodeLabelReader->read(ls)); deba@1845: it->second.touch(); deba@1409: } deba@1409: } deba@1845: for (typename NodeReaders::iterator it = readers.begin(); deba@1845: it != readers.end(); ++it) { deba@1845: if (!it->second.touched()) { deba@1845: ErrorMessage msg; deba@1845: msg << "Node not found in file: " << it->first; alpar@2153: throw IoParameterError(msg.message()); deba@1845: } deba@1845: } deba@1409: } deba@2000: deba@2000: virtual void missing() { deba@2000: if (readers.empty()) return; deba@2000: ErrorMessage msg; deba@2001: msg << "Nodes section not found in file: @nodes " << name; alpar@2153: throw IoParameterError(msg.message()); deba@2000: } deba@1409: deba@1409: private: deba@1409: deba@1901: std::string name; deba@1409: deba@1845: typedef std::map > NodeReaders; deba@1429: NodeReaders readers; deba@1901: std::auto_ptr<_reader_bits::LabelReaderBase > nodeLabelReader; deba@1409: }; deba@1409: deba@2016: /// \ingroup section_io deba@1409: /// \brief SectionReader for reading labeled edges. deba@1409: /// deba@1901: /// The edges section's header line is \c \@edges \c edges_name, but the deba@1901: /// \c edges_name may be empty. deba@1409: /// deba@1409: /// Each line in the section contains the name of the edge deba@1409: /// and then the edge id. deba@1409: /// deba@1409: /// \relates LemonReader deba@1409: template deba@1845: class EdgeReader : public LemonReader::SectionReader { deba@1845: typedef LemonReader::SectionReader Parent; deba@1409: typedef _Graph Graph; deba@1429: typedef typename Graph::Edge Edge; deba@1409: public: deba@1409: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for EdgeReader. It creates the EdgeReader and deba@1409: /// attach it into the given LemonReader. It will use the given deba@1409: /// edge id reader to give back the edges. The reader will read the deba@1901: /// section only if the \c _name and the \c edges_name are the same. deba@1901: template deba@1901: EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_reader), name(_name) { deba@1901: checkConcept<_reader_bits::ItemLabelReader, _LabelReader>(); deba@1901: edgeLabelReader.reset(new _reader_bits:: deba@1901: LabelReader(_labelReader)); deba@1476: } deba@1409: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for EdgeReader. deba@1409: virtual ~EdgeReader() {} deba@1409: private: deba@1409: EdgeReader(const EdgeReader&); deba@1409: void operator=(const EdgeReader&); deba@1409: deba@1409: public: deba@1409: deba@1409: /// \brief Add an edge reader command for the EdgeReader. deba@1409: /// deba@1409: /// Add an edge reader command for the EdgeReader. deba@2386: void readEdge(std::string label, Edge& item) { deba@2386: if (readers.find(label) != readers.end()) { deba@1409: ErrorMessage msg; deba@2386: msg << "Multiple read rule for edge: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1409: } deba@2386: readers.insert(make_pair(label, _reader_bits::ItemStore(item))); deba@1409: } deba@1409: deba@1409: protected: deba@1409: deba@1409: /// \brief Gives back true when the SectionReader can process deba@1409: /// the section with the given header line. deba@1409: /// deba@1421: /// It gives back true when the header line start with \c \@edges, deba@1901: /// and the header line's name and the reader's name are the same. deba@1421: virtual bool header(const std::string& line) { deba@1421: std::istringstream ls(line); deba@1421: std::string command; deba@1901: std::string id; klao@1997: ls >> command >> id; deba@1421: return command == "@edges" && name == id; deba@1421: } deba@1421: deba@1421: /// \brief Reader function of the section. deba@1421: /// deba@1421: /// It reads the content of the section. deba@1421: virtual void read(std::istream& is) { deba@1901: if (!edgeLabelReader->isLabelReader()) { deba@1901: throw DataFormatError("Cannot find edgeset or label map"); deba@1476: } deba@1421: std::string line; deba@1421: while (getline(is, line)) { deba@1421: std::istringstream ls(line); deba@1421: std::string id; deba@1421: ls >> id; deba@1429: typename EdgeReaders::iterator it = readers.find(id); deba@1421: if (it != readers.end()) { deba@1901: it->second.read(edgeLabelReader->read(ls)); deba@1845: it->second.touch(); deba@1421: } deba@1421: } deba@1845: for (typename EdgeReaders::iterator it = readers.begin(); deba@1845: it != readers.end(); ++it) { deba@1845: if (!it->second.touched()) { deba@1845: ErrorMessage msg; deba@1845: msg << "Edge not found in file: " << it->first; alpar@2153: throw IoParameterError(msg.message()); deba@1845: } deba@1845: } deba@1421: } deba@2000: deba@2000: virtual void missing() { deba@2000: if (readers.empty()) return; deba@2000: ErrorMessage msg; deba@2001: msg << "Edges section not found in file: @edges " << name; alpar@2153: throw IoParameterError(msg.message()); deba@2000: } deba@1421: deba@1421: private: deba@1421: deba@1901: std::string name; deba@1421: deba@1845: typedef std::map > EdgeReaders; deba@1429: EdgeReaders readers; deba@1901: std::auto_ptr<_reader_bits::LabelReaderBase > edgeLabelReader; deba@1421: }; deba@1421: deba@2016: /// \ingroup section_io deba@1421: /// \brief SectionReader for reading labeled undirected edges. deba@1421: /// klao@1909: /// The undirected edges section's header line is \c \@uedges klao@1909: /// \c uedges_name, but the \c uedges_name may be empty. deba@1421: /// deba@1421: /// Each line in the section contains the name of the undirected edge deba@1421: /// and then the undirected edge id. deba@1421: /// deba@1421: /// \relates LemonReader deba@1421: template klao@1909: class UEdgeReader : public LemonReader::SectionReader { deba@1845: typedef LemonReader::SectionReader Parent; deba@1421: typedef _Graph Graph; deba@1429: typedef typename Graph::Edge Edge; klao@1909: typedef typename Graph::UEdge UEdge; deba@1421: public: deba@1421: deba@1421: /// \brief Constructor. deba@1421: /// klao@1909: /// Constructor for UEdgeReader. It creates the UEdgeReader and deba@1421: /// attach it into the given LemonReader. It will use the given deba@1421: /// undirected edge id reader to give back the edges. The reader will klao@1909: /// read the section only if the \c _name and the \c uedges_name are deba@1421: /// the same. deba@1901: template klao@1909: UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_reader), name(_name) { klao@1909: checkConcept<_reader_bits::ItemLabelReader, _LabelReader>(); deba@1901: checkConcept<_reader_bits::ItemLabelReader, _LabelReader>(); deba@2467: uedgeLabelReader.reset(new _reader_bits:: deba@2467: LabelReader(_labelReader)); deba@1901: edgeLabelReader.reset(new _reader_bits:: deba@2467: LabelReader(_labelReader)); deba@1476: } deba@1421: deba@1421: /// \brief Destructor. deba@1421: /// klao@1909: /// Destructor for UEdgeReader. klao@1909: virtual ~UEdgeReader() {} deba@1421: private: klao@1909: UEdgeReader(const UEdgeReader&); klao@1909: void operator=(const UEdgeReader&); deba@1421: deba@1421: public: deba@1421: klao@1909: /// \brief Add an undirected edge reader command for the UEdgeReader. deba@1421: /// klao@1909: /// Add an undirected edge reader command for the UEdgeReader. deba@2386: void readUEdge(std::string label, UEdge& item) { deba@2467: if (uedgeReaders.find(label) != uedgeReaders.end()) { deba@1429: ErrorMessage msg; deba@2386: msg << "Multiple read rule for undirected edge: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1429: } deba@2467: uedgeReaders.insert(make_pair(label, _reader_bits:: klao@1909: ItemStore(item))); deba@1429: } deba@1429: klao@1909: /// \brief Add an edge reader command for the UEdgeReader. deba@1429: /// klao@1909: /// Add an edge reader command for the UEdgeReader. deba@2386: void readEdge(std::string label, Edge& item) { deba@2386: if (edgeReaders.find(label) != edgeReaders.end()) { deba@1421: ErrorMessage msg; deba@2386: msg << "Multiple read rule for edge: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1421: } deba@2386: edgeReaders.insert(make_pair(label, _reader_bits::ItemStore(item))); deba@1421: } deba@1421: deba@1421: protected: deba@1421: deba@1421: /// \brief Gives back true when the SectionReader can process deba@1421: /// the section with the given header line. deba@1421: /// deba@1421: /// It gives back true when the header line start with \c \@edges, deba@1901: /// and the header line's name and the reader's name are the same. deba@1409: virtual bool header(const std::string& line) { deba@1409: std::istringstream ls(line); deba@1409: std::string command; deba@1901: std::string id; klao@1997: ls >> command >> id; klao@1909: return command == "@uedges" && name == id; deba@1409: } deba@1409: deba@1409: /// \brief Reader function of the section. deba@1409: /// deba@1409: /// It reads the content of the section. deba@1409: virtual void read(std::istream& is) { deba@1901: if (!edgeLabelReader->isLabelReader()) { deba@1901: throw DataFormatError("Cannot find undirected edgeset or label map"); deba@1476: } deba@2467: if (!uedgeLabelReader->isLabelReader()) { deba@1901: throw DataFormatError("Cannot find undirected edgeset or label map"); deba@1476: } deba@1409: std::string line; deba@1409: while (getline(is, line)) { deba@1409: std::istringstream ls(line); deba@1409: std::string id; deba@1409: ls >> id; deba@1429: { deba@2467: typename UEdgeReaders::iterator it = uedgeReaders.find(id); deba@2467: if (it != uedgeReaders.end()) { deba@2467: it->second.read(uedgeLabelReader->read(ls)); deba@1845: it->second.touch(); deba@1845: continue; deba@1429: } deba@1429: } { deba@1429: typename EdgeReaders::iterator it = edgeReaders.find(id); deba@1429: if (it != edgeReaders.end()) { deba@1901: it->second.read(edgeLabelReader->read(ls)); deba@1845: it->second.touch(); deba@1845: continue; deba@1429: } deba@1429: } deba@1409: } deba@1845: for (typename EdgeReaders::iterator it = edgeReaders.begin(); deba@1845: it != edgeReaders.end(); ++it) { deba@1845: if (!it->second.touched()) { deba@1845: ErrorMessage msg; deba@1845: msg << "Edge not found in file: " << it->first; alpar@2153: throw IoParameterError(msg.message()); deba@1845: } deba@1845: } deba@2467: for (typename UEdgeReaders::iterator it = uedgeReaders.begin(); deba@2467: it != uedgeReaders.end(); ++it) { deba@1845: if (!it->second.touched()) { deba@1845: ErrorMessage msg; klao@1909: msg << "UEdge not found in file: " << it->first; alpar@2153: throw IoParameterError(msg.message()); deba@1845: } deba@1845: } deba@1409: } deba@2000: deba@2000: virtual void missing() { deba@2467: if (edgeReaders.empty() && uedgeReaders.empty()) return; deba@2000: ErrorMessage msg; deba@2001: msg << "UEdges section not found in file: @uedges " << name; alpar@2153: throw IoParameterError(msg.message()); deba@2000: } deba@1409: deba@1409: private: deba@1409: deba@1901: std::string name; deba@1409: deba@1845: typedef std::map > UEdgeReaders; deba@2467: UEdgeReaders uedgeReaders; deba@2467: std::auto_ptr<_reader_bits::LabelReaderBase > uedgeLabelReader; deba@1429: deba@1845: typedef std::map > EdgeReaders; deba@1429: EdgeReaders edgeReaders; deba@1901: std::auto_ptr<_reader_bits::LabelReaderBase > edgeLabelReader; deba@1409: }; deba@1409: deba@2016: /// \ingroup section_io deba@1409: /// \brief SectionReader for attributes. deba@1409: /// deba@1409: /// The lemon format can store multiple attribute set. Each set has deba@1901: /// the header line \c \@attributes \c attributeset_name, but the deba@1901: /// attributeset_name may be empty. deba@1409: /// deba@1409: /// The attributeset section contains several lines. Each of them starts deba@1409: /// with an attribute and then a the value for the id. deba@1409: /// deba@1409: /// \relates LemonReader deba@1408: template deba@1845: class AttributeReader : public LemonReader::SectionReader { deba@1845: typedef LemonReader::SectionReader Parent; deba@1408: typedef _Traits Traits; deba@1408: public: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for AttributeReader. It creates the AttributeReader and deba@1409: /// attach it into the given LemonReader. The reader process a section deba@1901: /// only if the \c section_name and the \c _name are the same. deba@1408: AttributeReader(LemonReader& _reader, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_reader), name(_name) {} deba@1408: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for AttributeReader. deba@1408: virtual ~AttributeReader() { deba@1408: for (typename Readers::iterator it = readers.begin(); deba@1408: it != readers.end(); ++it) { deba@1408: delete it->second; deba@1408: } deba@1408: } deba@1408: deba@1408: private: deba@1408: AttributeReader(const AttributeReader&); deba@1408: void operator=(AttributeReader&); deba@1408: deba@1408: public: deba@1409: /// \brief Add an attribute reader command for the reader. deba@1409: /// deba@1409: /// Add an attribute reader command for the reader. deba@1408: template deba@2416: AttributeReader& readAttribute(const std::string& label, Value& value) { deba@1408: return readAttribute > deba@2416: (label, value); deba@1408: } deba@1408: deba@1409: /// \brief Add an attribute reader command for the reader. deba@1409: /// deba@1409: /// Add an attribute reader command for the reader. deba@2386: template deba@2416: AttributeReader& readAttribute(const std::string& label, Value& value, deba@2386: const ItemReader& ir = ItemReader()) { deba@2386: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2386: if (readers.find(label) != readers.end()) { deba@1408: ErrorMessage msg; deba@2386: msg << "Multiple read rule for attribute: " << label; alpar@2153: throw IoParameterError(msg.message()); deba@1408: } deba@2386: readers.insert(make_pair(label, new _reader_bits:: deba@2386: ValueReader(value, ir))); deba@1408: return *this; deba@1408: } deba@1408: deba@1409: protected: deba@1409: deba@1409: /// \brief Gives back true when the SectionReader can process deba@1409: /// the section with the given header line. deba@1409: /// deba@1421: /// It gives back true when the header line start with \c \@attributes, deba@1409: /// and the header line's id and the attributeset's id are the same. deba@1408: bool header(const std::string& line) { deba@1408: std::istringstream ls(line); deba@1408: std::string command; deba@1901: std::string id; klao@1997: ls >> command >> id; deba@1408: return command == "@attributes" && name == id; deba@1408: } deba@1408: deba@1409: /// \brief Reader function of the section. deba@1409: /// deba@1409: /// It reads the content of the section. deba@1408: void read(std::istream& is) { deba@1408: std::string line; deba@1408: while (getline(is, line)) { deba@1408: std::istringstream ls(line); deba@1408: std::string id; deba@1408: ls >> id; deba@1408: typename Readers::iterator it = readers.find(id); deba@1408: if (it != readers.end()) { deba@1408: it->second->read(ls); deba@1901: it->second->touch(); deba@1408: } deba@1408: } deba@1846: for (typename Readers::iterator it = readers.begin(); deba@1846: it != readers.end(); ++it) { deba@1846: if (!it->second->touched()) { deba@1846: ErrorMessage msg; deba@1846: msg << "Attribute not found in file: " << it->first; alpar@2153: throw IoParameterError(msg.message()); deba@1846: } deba@1846: } deba@1408: } deba@2416: deba@2000: virtual void missing() { deba@2000: if (readers.empty()) return; deba@2000: ErrorMessage msg; deba@2001: msg << "Attribute section not found in file: @attributes " << name; alpar@2153: throw IoParameterError(msg.message()); deba@2000: } deba@2000: deba@1408: private: deba@1901: std::string name; deba@1408: deba@1845: typedef std::map Readers; deba@1409: Readers readers; deba@1408: }; deba@1408: deba@2016: /// \ingroup section_io deba@2467: /// \brief SectionReader for reading extra node maps. deba@2467: /// deba@2467: /// The lemon format can store maps in the nodeset sections. This deba@2467: /// class let you make distinict section to store maps. The main deba@2467: /// purpose of this class is a logical separation of some maps. The deba@2467: /// other useful application could be to store paths in node maps. deba@2467: /// deba@2467: /// The first line of the section contains the names of the maps deba@2467: /// separated with white spaces. Each next line describes an item deba@2467: /// in the itemset, and contains in the first column the label of deba@2467: /// the item and then the mapped values for each map. deba@2467: /// deba@2467: /// \relates LemonReader deba@2467: template deba@2467: class NodeMapReader : public LemonReader::SectionReader { deba@2467: typedef LemonReader::SectionReader Parent; deba@2467: public: deba@2467: deba@2467: typedef _Graph Graph; deba@2467: typedef typename Graph::Node Node; deba@2467: typedef _Traits Traits; deba@2467: typedef typename Traits::Skipper DefaultSkipper; deba@2467: deba@2467: /// \brief Constructor. deba@2467: /// deba@2467: /// Constructor for NodeMapReader. It creates the NodeMapReader and deba@2467: /// attach it into the given LemonReader. The reader will read deba@2467: /// the section when the \c section_name and the \c _name are the same. deba@2467: template deba@2467: NodeMapReader(LemonReader& _reader, deba@2467: const Graph& _graph, deba@2467: const _LabelReader& _labelReader, deba@2467: const std::string& _name = std::string(), deba@2467: const DefaultSkipper& _skipper = DefaultSkipper()) deba@2467: : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { deba@2467: labelReader.reset(new _reader_bits:: deba@2467: LabelReader(_labelReader)); deba@2467: } deba@2467: deba@2467: deba@2467: /// \brief Destructor. deba@2467: /// deba@2467: /// Destructor for NodeMapReader. deba@2467: virtual ~NodeMapReader() { deba@2467: for (typename MapReaders::iterator it = readers.begin(); deba@2467: it != readers.end(); ++it) { deba@2467: delete it->second; deba@2467: } deba@2467: } deba@2467: deba@2467: private: deba@2467: NodeMapReader(const NodeMapReader&); deba@2467: void operator=(const NodeMapReader&); deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new node map reader command for the reader. deba@2467: /// deba@2467: /// Add a new node map reader command for the reader. deba@2467: template deba@2467: NodeMapReader& readNodeMap(std::string label, Map& map) { deba@2467: return _readMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: template deba@2467: NodeMapReader& readNodeMap(std::string label, const Map& map) { deba@2467: return _readMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new node map reader command for the reader. deba@2467: /// deba@2467: /// Add a new node map reader command for the reader. deba@2467: template deba@2467: NodeMapReader& readNodeMap(std::string label, Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readMap::Type> deba@2467: (label, map, ir); deba@2467: } deba@2467: deba@2467: template deba@2467: NodeMapReader& readNodeMap(std::string label, const Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readMap::Type> deba@2467: (label, map, ir); deba@2467: } deba@2467: deba@2467: private: deba@2467: deba@2467: template deba@2467: NodeMapReader& _readMap(std::string label, MapParameter map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: checkConcept, Map>(); deba@2467: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2467: if (readers.find(label) != readers.end()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Multiple read rule for map: " << label; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: readers.insert( deba@2467: make_pair(label, new _reader_bits:: deba@2467: MapReader(map, ir))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new node map skipper command for the reader. deba@2467: /// deba@2467: /// Add a new node map skipper command for the reader. deba@2467: template deba@2467: NodeMapReader& skipNodeMap(std::string label, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: if (readers.find(label) != readers.end()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Multiple read rule for map: " << label; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: readers.insert(make_pair(label, new _reader_bits:: deba@2467: SkipReader(ir))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: protected: deba@2467: deba@2467: /// \brief Gives back true when the SectionReader can process deba@2467: /// the section with the given header line. deba@2467: /// deba@2467: /// It gives back true when the header line starts with \c \@mapset, deba@2467: /// and the header line's name and the mapset's name are the same. deba@2467: virtual bool header(const std::string& line) { deba@2467: std::istringstream ls(line); deba@2467: std::string command; deba@2467: std::string id; deba@2467: ls >> command >> id; deba@2467: return command == "@nodemaps" && name == id; deba@2467: } deba@2467: deba@2467: /// \brief Reader function of the section. deba@2467: /// deba@2467: /// It reads the content of the section. deba@2467: virtual void read(std::istream& is) { deba@2467: std::vector<_reader_bits::MapReaderBase* > index; deba@2467: std::string line; deba@2467: deba@2467: { deba@2467: getline(is, line); deba@2467: std::istringstream ls(line); deba@2467: std::string id; deba@2467: while (ls >> id) { deba@2467: typename MapReaders::iterator it = readers.find(id); deba@2467: if (it != readers.end()) { deba@2467: it->second->touch(); deba@2467: index.push_back(it->second); deba@2467: } else { deba@2467: index.push_back(&skipper); deba@2467: } deba@2467: } deba@2467: } deba@2467: for (typename MapReaders::iterator it = readers.begin(); deba@2467: it != readers.end(); ++it) { deba@2467: if (!it->second->touched()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Map not found in file: " << it->first; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: } deba@2467: while (getline(is, line)) { deba@2467: std::istringstream ls(line); deba@2467: Node node = labelReader->read(ls); deba@2467: for (int i = 0; i < int(index.size()); ++i) { deba@2467: index[i]->read(ls, node); deba@2467: } deba@2467: } deba@2467: } deba@2467: deba@2467: virtual void missing() { deba@2467: if (readers.empty()) return; deba@2467: ErrorMessage msg; deba@2467: msg << "NodeMap section not found in file: @nodemaps " << name; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: deba@2467: private: deba@2467: deba@2467: typedef std::map*> MapReaders; deba@2467: MapReaders readers; deba@2467: deba@2467: const Graph& graph; deba@2467: std::string name; deba@2467: _reader_bits::SkipReader skipper; deba@2467: std::auto_ptr<_reader_bits::LabelReaderBase > labelReader; deba@2467: deba@2467: }; deba@2467: deba@2467: /// \ingroup section_io deba@2467: /// \brief SectionReader for reading extra edge maps. deba@2467: /// deba@2467: /// The lemon format can store maps in the edgeset sections. This deba@2467: /// class let you make distinict section to store maps. The main deba@2467: /// purpose of this class is a logical separation of some maps. The deba@2467: /// other useful application could be to store paths in edge maps. deba@2467: /// deba@2467: /// The first line of the section contains the names of the maps deba@2467: /// separated with white spaces. Each next line describes an item deba@2467: /// in the itemset, and contains in the first column the label of deba@2467: /// the item and then the mapped values for each map. deba@2467: /// deba@2467: /// \relates LemonReader deba@2467: template deba@2467: class EdgeMapReader : public LemonReader::SectionReader { deba@2467: typedef LemonReader::SectionReader Parent; deba@2467: public: deba@2467: deba@2467: typedef _Graph Graph; deba@2467: typedef typename Graph::Edge Edge; deba@2467: typedef _Traits Traits; deba@2467: typedef typename Traits::Skipper DefaultSkipper; deba@2467: deba@2467: /// \brief Constructor. deba@2467: /// deba@2467: /// Constructor for EdgeMapReader. It creates the EdgeMapReader and deba@2467: /// attach it into the given LemonReader. The reader will read deba@2467: /// the section when the \c section_name and the \c _name are the same. deba@2467: template deba@2467: EdgeMapReader(LemonReader& _reader, deba@2467: const Graph& _graph, deba@2467: const _LabelReader& _labelReader, deba@2467: const std::string& _name = std::string(), deba@2467: const DefaultSkipper& _skipper = DefaultSkipper()) deba@2467: : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { deba@2467: labelReader.reset(new _reader_bits:: deba@2467: LabelReader(_labelReader)); deba@2467: } deba@2467: deba@2467: deba@2467: /// \brief Destructor. deba@2467: /// deba@2467: /// Destructor for EdgeMapReader. deba@2467: virtual ~EdgeMapReader() { deba@2467: for (typename MapReaders::iterator it = readers.begin(); deba@2467: it != readers.end(); ++it) { deba@2467: delete it->second; deba@2467: } deba@2467: } deba@2467: deba@2467: private: deba@2467: EdgeMapReader(const EdgeMapReader&); deba@2467: void operator=(const EdgeMapReader&); deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new edge map reader command for the reader. deba@2467: /// deba@2467: /// Add a new edge map reader command for the reader. deba@2467: template deba@2467: EdgeMapReader& readEdgeMap(std::string label, Map& map) { deba@2467: return _readMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: template deba@2467: EdgeMapReader& readEdgeMap(std::string label, const Map& map) { deba@2467: return _readMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new edge map reader command for the reader. deba@2467: /// deba@2467: /// Add a new edge map reader command for the reader. deba@2467: template deba@2467: EdgeMapReader& readEdgeMap(std::string label, Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readMap::Type> deba@2467: (label, map, ir); deba@2467: } deba@2467: deba@2467: template deba@2467: EdgeMapReader& readEdgeMap(std::string label, const Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readMap::Type> deba@2467: (label, map, ir); deba@2467: } deba@2467: deba@2467: private: deba@2467: deba@2467: template deba@2467: EdgeMapReader& _readMap(std::string label, MapParameter map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: checkConcept, Map>(); deba@2467: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2467: if (readers.find(label) != readers.end()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Multiple read rule for map: " << label; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: readers.insert( deba@2467: make_pair(label, new _reader_bits:: deba@2467: MapReader(map, ir))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new edge map skipper command for the reader. deba@2467: /// deba@2467: /// Add a new edge map skipper command for the reader. deba@2467: template deba@2467: EdgeMapReader& skipEdgeMap(std::string label, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: if (readers.find(label) != readers.end()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Multiple read rule for map: " << label; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: readers.insert(make_pair(label, new _reader_bits:: deba@2467: SkipReader(ir))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: protected: deba@2467: deba@2467: /// \brief Gives back true when the SectionReader can process deba@2467: /// the section with the given header line. deba@2467: /// deba@2467: /// It gives back true when the header line starts with \c \@mapset, deba@2467: /// and the header line's name and the mapset's name are the same. deba@2467: virtual bool header(const std::string& line) { deba@2467: std::istringstream ls(line); deba@2467: std::string command; deba@2467: std::string id; deba@2467: ls >> command >> id; deba@2467: return (command == "@edgemaps" || command == "@uedgemaps") && name == id; deba@2467: } deba@2467: deba@2467: /// \brief Reader function of the section. deba@2467: /// deba@2467: /// It reads the content of the section. deba@2467: virtual void read(std::istream& is) { deba@2467: std::vector<_reader_bits::MapReaderBase* > index; deba@2467: std::string line; deba@2467: deba@2467: { deba@2467: getline(is, line); deba@2467: std::istringstream ls(line); deba@2467: std::string id; deba@2467: while (ls >> id) { deba@2467: typename MapReaders::iterator it = readers.find(id); deba@2467: if (it != readers.end()) { deba@2467: it->second->touch(); deba@2467: index.push_back(it->second); deba@2467: } else { deba@2467: index.push_back(&skipper); deba@2467: } deba@2467: } deba@2467: } deba@2467: for (typename MapReaders::iterator it = readers.begin(); deba@2467: it != readers.end(); ++it) { deba@2467: if (!it->second->touched()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Map not found in file: " << it->first; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: } deba@2467: while (getline(is, line)) { deba@2467: std::istringstream ls(line); deba@2467: Edge edge = labelReader->read(ls); deba@2467: for (int i = 0; i < int(index.size()); ++i) { deba@2467: index[i]->read(ls, edge); deba@2467: } deba@2467: } deba@2467: } deba@2467: deba@2467: virtual void missing() { deba@2467: if (readers.empty()) return; deba@2467: ErrorMessage msg; deba@2467: msg << "EdgeMap section not found in file: @edgemaps " << name; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: deba@2467: private: deba@2467: deba@2467: typedef std::map*> MapReaders; deba@2467: MapReaders readers; deba@2467: deba@2467: const Graph& graph; deba@2467: std::string name; deba@2467: _reader_bits::SkipReader skipper; deba@2467: std::auto_ptr<_reader_bits::LabelReaderBase > labelReader; deba@2467: deba@2467: }; deba@2467: deba@2467: /// \ingroup section_io deba@2467: /// \brief SectionReader for reading extra undirected edge maps. deba@2467: /// deba@2467: /// The lemon format can store maps in the uedgeset sections. This deba@2467: /// class let you make distinict section to store maps. The main deba@2467: /// purpose of this class is a logical separation of some maps. The deba@2467: /// other useful application could be to store paths in undirected deba@2467: /// edge maps. deba@2467: /// deba@2467: /// The first line of the section contains the names of the maps deba@2467: /// separated with white spaces. Each next line describes an item deba@2467: /// in the itemset, and contains in the first column the label of deba@2467: /// the item and then the mapped values for each map. deba@2467: /// deba@2467: /// \relates LemonReader deba@2467: template deba@2467: class UEdgeMapReader : public LemonReader::SectionReader { deba@2467: typedef LemonReader::SectionReader Parent; deba@2467: public: deba@2467: deba@2467: typedef _Graph Graph; deba@2467: typedef typename Graph::Edge Edge; deba@2467: typedef typename Graph::UEdge UEdge; deba@2467: typedef _Traits Traits; deba@2467: typedef typename Traits::Skipper DefaultSkipper; deba@2467: deba@2467: /// \brief Constructor. deba@2467: /// deba@2467: /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and deba@2467: /// attach it into the given LemonReader. The reader will read deba@2467: /// the section when the \c section_name and the \c _name are the same. deba@2467: template deba@2467: UEdgeMapReader(LemonReader& _reader, const Graph& _graph, deba@2467: const _LabelReader& _labelReader, deba@2467: const std::string& _name = std::string(), deba@2467: const DefaultSkipper& _skipper = DefaultSkipper()) deba@2467: : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { deba@2467: labelReader.reset(new _reader_bits:: deba@2467: LabelReader(_labelReader)); deba@2467: } deba@2467: deba@2467: deba@2467: /// \brief Destructor. deba@2467: /// deba@2467: /// Destructor for UEdgeMapReader. deba@2467: virtual ~UEdgeMapReader() { deba@2467: for (typename MapReaders::iterator it = readers.begin(); deba@2467: it != readers.end(); ++it) { deba@2467: delete it->second; deba@2467: } deba@2467: } deba@2467: deba@2467: private: deba@2467: UEdgeMapReader(const UEdgeMapReader&); deba@2467: void operator=(const UEdgeMapReader&); deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new undirected edge map reader command for the deba@2467: /// reader. deba@2467: /// deba@2467: /// Add a new undirected edge map reader command for the reader. deba@2467: template deba@2467: UEdgeMapReader& readUEdgeMap(std::string label, Map& map) { deba@2467: return _readMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: template deba@2467: UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) { deba@2467: return _readMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new undirected edge map reader command for the deba@2467: /// reader. deba@2467: /// deba@2467: /// Add a new undirected edge map reader command for the reader. deba@2467: template deba@2467: UEdgeMapReader& readUEdgeMap(std::string label, Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readMap::Type> deba@2467: (label, map, ir); deba@2467: } deba@2467: deba@2467: template deba@2467: UEdgeMapReader& readUEdgeMap(std::string label, const Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readMap::Type> deba@2467: (label, map, ir); deba@2467: } deba@2467: deba@2467: private: deba@2467: deba@2467: template deba@2467: UEdgeMapReader& _readMap(std::string label, MapParameter map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: checkConcept, Map>(); deba@2467: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2467: if (readers.find(label) != readers.end()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Multiple read rule for map: " << label; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: readers.insert( deba@2467: make_pair(label, new _reader_bits:: deba@2467: MapReader(map, ir))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new undirected edge map skipper command for the deba@2467: /// reader. deba@2467: /// deba@2467: /// Add a new undirected edge map skipper command for the reader. deba@2467: template deba@2467: UEdgeMapReader& skipUEdgeMap(std::string label, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: if (readers.find(label) != readers.end()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Multiple read rule for map: " << label; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: readers.insert(make_pair(label, new _reader_bits:: deba@2467: SkipReader(ir))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: /// \brief Add a new directed edge map reader command for the reader. deba@2467: /// deba@2467: /// Add a new directed edge map reader command for the reader. deba@2467: template deba@2467: UEdgeMapReader& readEdgeMap(std::string label, Map& map) { deba@2467: return _readDirMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: template deba@2467: UEdgeMapReader& readEdgeMap(std::string label, const Map& map) { deba@2467: return _readDirMap< deba@2467: typename Traits::template Reader, Map, deba@2467: typename _reader_bits::Arg::Type>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new directed edge map reader command for the reader. deba@2467: /// deba@2467: /// Add a new directed edge map reader command for the reader. deba@2467: template deba@2467: UEdgeMapReader& readEdgeMap(std::string label, Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readDirMap::Type>(label, map, ir); deba@2467: } deba@2467: deba@2467: template deba@2467: UEdgeMapReader& readEdgeMap(std::string label, const Map& map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: return _readDirMap::Type>(label, map, ir); deba@2467: } deba@2467: deba@2467: private: deba@2467: deba@2467: template deba@2467: UEdgeMapReader& _readDirMap(std::string label, MapParameter map, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: checkConcept<_reader_bits::ItemReader, ItemReader>(); deba@2467: checkConcept, Map>(); deba@2467: readUEdgeMap("+" + label, deba@2467: _reader_bits::forwardComposeMap(graph, map), ir); deba@2467: readUEdgeMap("-" + label, deba@2467: _reader_bits::backwardComposeMap(graph, map), ir); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new directed edge map skipper command for the reader. deba@2467: /// deba@2467: /// Add a new directed edge map skipper command for the reader. deba@2467: template deba@2467: UEdgeMapReader& skipEdgeMap(std::string label, deba@2467: const ItemReader& ir = ItemReader()) { deba@2467: skipUEdgeMap("+" + label, ir); deba@2467: skipUEdgeMap("-" + label, ir); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: protected: deba@2467: deba@2467: /// \brief Gives back true when the SectionReader can process deba@2467: /// the section with the given header line. deba@2467: /// deba@2467: /// It gives back true when the header line starts with \c \@mapset, deba@2467: /// and the header line's name and the mapset's name are the same. deba@2467: virtual bool header(const std::string& line) { deba@2467: std::istringstream ls(line); deba@2467: std::string command; deba@2467: std::string id; deba@2467: ls >> command >> id; deba@2467: return (command == "@edgemaps" || command == "@uedgemaps") && name == id; deba@2467: } deba@2467: deba@2467: /// \brief Reader function of the section. deba@2467: /// deba@2467: /// It reads the content of the section. deba@2467: virtual void read(std::istream& is) { deba@2467: std::vector<_reader_bits::MapReaderBase* > index; deba@2467: std::string line; deba@2467: deba@2467: { deba@2467: getline(is, line); deba@2467: std::istringstream ls(line); deba@2467: std::string id; deba@2467: while (ls >> id) { deba@2467: typename MapReaders::iterator it = readers.find(id); deba@2467: if (it != readers.end()) { deba@2467: it->second->touch(); deba@2467: index.push_back(it->second); deba@2467: } else { deba@2467: index.push_back(&skipper); deba@2467: } deba@2467: } deba@2467: } deba@2467: for (typename MapReaders::iterator it = readers.begin(); deba@2467: it != readers.end(); ++it) { deba@2467: if (!it->second->touched()) { deba@2467: ErrorMessage msg; deba@2467: msg << "Map not found in file: " << it->first; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: } deba@2467: while (getline(is, line)) { deba@2467: std::istringstream ls(line); deba@2467: UEdge uedge = labelReader->read(ls); deba@2467: for (int i = 0; i < int(index.size()); ++i) { deba@2467: index[i]->read(ls, uedge); deba@2467: } deba@2467: } deba@2467: } deba@2467: deba@2467: virtual void missing() { deba@2467: if (readers.empty()) return; deba@2467: ErrorMessage msg; deba@2467: msg << "UEdgeMap section not found in file: @uedgemaps " << name; deba@2467: throw IoParameterError(msg.message()); deba@2467: } deba@2467: deba@2467: private: deba@2467: deba@2467: const Graph& graph; deba@2467: std::string name; deba@2467: deba@2467: typedef std::map*> MapReaders; deba@2467: deba@2467: MapReaders readers; deba@2467: _reader_bits::SkipReader skipper; deba@2467: deba@2467: std::auto_ptr<_reader_bits::LabelReaderBase > labelReader; deba@2467: deba@2467: }; deba@2467: deba@2467: /// \ingroup section_io deba@1423: /// \brief SectionReader for retrieve what is in the file. deba@1423: /// deba@1423: /// SectionReader for retrieve what is in the file. If you want deba@1423: /// to know which sections, maps and items are in the file deba@1423: /// use the next code: alpar@1946: ///\code deba@1423: /// LemonReader reader("input.lgf"); deba@1423: /// ContentReader content(reader); deba@1423: /// reader.run(); alpar@1946: ///\endcode deba@1423: class ContentReader : public LemonReader::SectionReader { deba@1423: typedef LemonReader::SectionReader Parent; deba@1423: public: deba@1423: /// \brief Constructor. deba@1423: /// deba@1423: /// Constructor for deba@1423: ContentReader(LemonReader& _reader) : Parent(_reader) {} deba@1423: deba@1423: /// \brief Desctructor. deba@1423: /// deba@1423: /// Desctructor. deba@1423: virtual ~ContentReader() {} deba@1423: deba@1423: /// \brief Gives back how many nodesets are in the file. deba@1423: /// deba@1423: /// Gives back how many nodesets are in the file. deba@1423: int nodeSetNum() const { deba@1423: return nodesets.size(); deba@1423: } deba@1423: deba@1423: /// \brief Gives back the name of nodeset on the indiced position. deba@1423: /// deba@1423: /// Gives back the name of nodeset on the indiced position. deba@1423: std::string nodeSetName(int index) const { deba@1423: return nodesets[index].name; deba@1423: } deba@1423: deba@1423: /// \brief Gives back the map names of nodeset on the indiced position. deba@1423: /// deba@1423: /// Gives back the map names of nodeset on the indiced position. deba@1423: const std::vector& nodeSetMaps(int index) const { deba@1423: return nodesets[index].items; deba@1423: } deba@1423: deba@1423: /// \brief Gives back how many edgesets are in the file. deba@1423: /// deba@1423: /// Gives back how many edgesets are in the file. deba@1423: int edgeSetNum() const { deba@1423: return edgesets.size(); deba@1423: } deba@1423: deba@1423: /// \brief Gives back the name of edgeset on the indiced position. deba@1423: /// deba@1423: /// Gives back the name of edgeset on the indiced position. deba@1423: std::string edgeSetName(int index) const { deba@1423: return edgesets[index].name; deba@1423: } deba@1423: deba@1423: /// \brief Gives back the map names of edgeset on the indiced position. deba@1423: /// deba@1423: /// Gives back the map names of edgeset on the indiced position. deba@1423: const std::vector& edgeSetMaps(int index) const { deba@1423: return edgesets[index].items; deba@1423: } deba@1423: deba@1423: /// \brief Gives back how many undirected edgesets are in the file. deba@1423: /// deba@1423: /// Gives back how many undirected edgesets are in the file. klao@1909: int uEdgeSetNum() const { klao@1909: return uedgesets.size(); deba@1423: } deba@1423: deba@1423: /// \brief Gives back the name of undirected edgeset on the indiced deba@1423: /// position. deba@1423: /// deba@1423: /// Gives back the name of undirected edgeset on the indiced position. klao@1909: std::string uEdgeSetName(int index) const { klao@1909: return uedgesets[index].name; deba@1423: } deba@1423: deba@1423: /// \brief Gives back the map names of undirected edgeset on the indiced deba@1423: /// position. deba@1423: /// deba@1423: /// Gives back the map names of undirected edgeset on the indiced position. klao@1909: const std::vector& uEdgeSetMaps(int index) const { klao@1909: return uedgesets[index].items; deba@1423: } deba@1423: deba@1423: /// \brief Gives back how many labeled nodes section are in the file. deba@1423: /// deba@1423: /// Gives back how many labeled nodes section are in the file. deba@1423: int nodesNum() const { deba@1423: return nodes.size(); deba@1423: } deba@1423: deba@1423: /// \brief Gives back the name of labeled nodes section on the indiced deba@1423: /// position. deba@1423: /// deba@1423: /// Gives back the name of labeled nodes section on the indiced position. deba@1423: std::string nodesName(int index) const { deba@1423: return nodes[index].name; deba@1423: } deba@1423: deba@1423: /// \brief Gives back the names of the labeled nodes in the indiced deba@1423: /// section. deba@1423: /// deba@1423: /// Gives back the names of the labeled nodes in the indiced section. deba@1423: const std::vector& nodesItems(int index) const { deba@1423: return nodes[index].items; deba@1423: } deba@1423: deba@1423: /// \brief Gives back how many labeled edges section are in the file. deba@1423: /// deba@1423: /// Gives back how many labeled edges section are in the file. deba@1423: int edgesNum() const { deba@1423: return edges.size(); deba@1423: } deba@1423: deba@1423: /// \brief Gives back the name of labeled edges section on the indiced deba@1423: /// position. deba@1423: /// deba@1423: /// Gives back the name of labeled edges section on the indiced position. deba@1423: std::string edgesName(int index) const { deba@1423: return edges[index].name; deba@1423: } deba@1423: deba@1423: /// \brief Gives back the names of the labeled edges in the indiced deba@1423: /// section. deba@1423: /// deba@1423: /// Gives back the names of the labeled edges in the indiced section. deba@1423: const std::vector& edgesItems(int index) const { deba@1423: return edges[index].items; deba@1423: } deba@1423: deba@1423: /// \brief Gives back how many labeled undirected edges section are deba@1423: /// in the file. deba@1423: /// deba@1423: /// Gives back how many labeled undirected edges section are in the file. klao@1909: int uEdgesNum() const { klao@1909: return uedges.size(); deba@1423: } deba@1423: deba@1423: /// \brief Gives back the name of labeled undirected edges section deba@1423: /// on the indiced position. deba@1423: /// deba@1423: /// Gives back the name of labeled undirected edges section on the deba@1423: /// indiced position. klao@1909: std::string uEdgesName(int index) const { klao@1909: return uedges[index].name; deba@1423: } deba@1423: deba@1423: /// \brief Gives back the names of the labeled undirected edges in deba@1423: /// the indiced section. deba@1423: /// deba@1423: /// Gives back the names of the labeled undirected edges in the deba@1423: /// indiced section. klao@1909: const std::vector& uEdgesItems(int index) const { klao@1909: return uedges[index].items; deba@1423: } deba@1423: deba@1423: deba@1423: /// \brief Gives back how many attributes section are in the file. deba@1423: /// deba@1423: /// Gives back how many attributes section are in the file. deba@1423: int attributesNum() const { deba@1423: return attributes.size(); deba@1423: } deba@1423: deba@1423: /// \brief Gives back the name of attributes section on the indiced deba@1423: /// position. deba@1423: /// deba@1423: /// Gives back the name of attributes section on the indiced position. deba@1423: std::string attributesName(int index) const { deba@1423: return attributes[index].name; deba@1423: } deba@1423: deba@1423: /// \brief Gives back the names of the attributes in the indiced section. deba@1423: /// deba@1423: /// Gives back the names of the attributes in the indiced section. deba@1423: const std::vector& attributesItems(int index) const { deba@1423: return attributes[index].items; deba@1423: } deba@1423: deba@1423: const std::vector& otherSections() const { deba@1423: return sections; deba@1423: } deba@1423: deba@1423: protected: deba@1423: deba@1423: /// \brief Gives back true when the SectionReader can process deba@1423: /// the section with the given header line. deba@1423: /// deba@1423: /// It gives back true when the section is common section. deba@1423: bool header(const std::string& line) { deba@1423: std::istringstream ls(line); deba@1423: std::string command, name; deba@1423: ls >> command >> name; deba@1423: if (command == "@nodeset") { deba@1423: current = command; deba@1423: nodesets.push_back(SectionInfo(name)); deba@1423: } else if (command == "@edgeset") { deba@1423: current = command; deba@1423: edgesets.push_back(SectionInfo(name)); klao@1909: } else if (command == "@uedgeset") { deba@1423: current = command; klao@1909: uedgesets.push_back(SectionInfo(name)); deba@1423: } else if (command == "@nodes") { deba@1423: current = command; deba@1423: nodes.push_back(SectionInfo(name)); deba@1423: } else if (command == "@edges") { deba@1423: current = command; deba@1423: edges.push_back(SectionInfo(name)); klao@1909: } else if (command == "@uedges") { deba@1423: current = command; klao@1909: uedges.push_back(SectionInfo(name)); deba@1423: } else if (command == "@attributes") { deba@1423: current = command; deba@1423: attributes.push_back(SectionInfo(name)); deba@1423: } else { deba@1423: sections.push_back(line); deba@1423: return false; deba@1423: } deba@1423: return true; deba@1423: } deba@1423: deba@1423: /// \brief Retrieve the items from various sections. deba@1423: /// deba@1423: /// Retrieve the items from various sections. deba@1423: void read(std::istream& is) { deba@1423: if (current == "@nodeset") { deba@1423: readMapNames(is, nodesets.back().items); deba@1423: } else if (current == "@edgeset") { deba@1423: readMapNames(is, edgesets.back().items); klao@1909: } else if (current == "@uedgeset") { klao@1909: readMapNames(is, uedgesets.back().items); deba@1423: } else if (current == "@nodes") { deba@1423: readItemNames(is, nodes.back().items); deba@1423: } else if (current == "@edges") { deba@1423: readItemNames(is, edges.back().items); klao@1909: } else if (current == "@uedges") { klao@1909: readItemNames(is, uedges.back().items); deba@1423: } else if (current == "@attributes") { deba@1423: readItemNames(is, attributes.back().items); deba@1423: } deba@1423: } deba@1423: deba@1423: private: deba@1423: deba@1423: void readMapNames(std::istream& is, std::vector& maps) { deba@1901: std::string line, name; deba@1423: std::getline(is, line); deba@1423: std::istringstream ls(line); deba@1901: while (ls >> name) { deba@1901: maps.push_back(name); deba@1423: } deba@1423: while (getline(is, line)); deba@1423: } deba@1423: deba@1423: void readItemNames(std::istream& is, std::vector& maps) { deba@1901: std::string line, name; deba@1423: while (std::getline(is, line)) { deba@1423: std::istringstream ls(line); deba@1901: ls >> name; deba@1901: maps.push_back(name); deba@1423: } deba@1423: } deba@1423: deba@1423: struct SectionInfo { deba@1423: std::string name; deba@1423: std::vector items; deba@1423: deba@1423: SectionInfo(const std::string& _name) : name(_name) {} deba@1423: }; deba@1423: deba@1423: std::vector nodesets; deba@1423: std::vector edgesets; klao@1909: std::vector uedgesets; deba@1423: deba@1423: std::vector nodes; deba@1423: std::vector edges; klao@1909: std::vector uedges; deba@1423: deba@1423: std::vector attributes; deba@1423: deba@1423: std::vector sections; deba@1423: deba@1423: std::string current; deba@1423: deba@1423: }; deba@1423: deba@1408: } deba@1408: #endif