diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lemon_reader.h --- a/src/lemon/lemon_reader.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1977 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup io_group -///\file -///\brief Lemon Format reader. - - -#ifndef LEMON_LEMON_READER_H -#define LEMON_LEMON_READER_H - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -namespace lemon { - - namespace _reader_bits { - - template - bool operator<(T, T) { - throw DataFormatError("Id is not comparable"); - } - - template - struct Less { - bool operator()(const T& p, const T& q) const { - return p < q; - } - }; - - template - class WriteComposeMap { - public: - typedef True NeedCopy; - - typedef typename M2::Key Key; - typedef typename M1::Value Value; - - WriteComposeMap(typename SmartParameter::Type _m1, const M2& _m2) - : m1(_m1), m2(_m2) {} - - void set(const Key& key, const Value& value) { - m1.set(m2[key], value); - } - - private: - - typename SmartReference::Type m1; - typename SmartConstReference::Type m2; - - }; - - template - WriteComposeMap writeComposeMap(M1& m1, const M2& m2) { - return WriteComposeMap(m1, m2); - } - - template - WriteComposeMap writeComposeMap(const M1& m1, const M2& m2) { - return WriteComposeMap(m1, m2); - } - - } - - /// \ingroup io_group - /// \brief Lemon Format reader class. - /// - /// The Lemon Format contains several sections. We do not want to - /// determine what sections are in a lemon file we give only a framework - /// to read a section oriented format. - /// - /// In the Lemon Format each section starts with a line contains a \c \@ - /// character on the first not white space position. This line is the - /// header line of the section. Each next lines belong to this section - /// while it does not starts with \c \@ character. This line can start a - /// new section or if it can close the file with the \c \@end line. - /// The file format ignore the empty and comment lines. The line is - /// comment line if it starts with a \c # character. - /// - /// The framework provides an abstract LemonReader::SectionReader class - /// what defines the interface of a SectionReader. The SectionReader - /// has the \c header() member function what get a header line string and - /// decides if it want to process the next section. Several SectionReaders - /// can be attached to an LemonReader and the first attached what can - /// process the section will be used. Its \c read() member will called - /// with a stream contains the section. From this stream the empty and - /// comment lines are filtered out. - /// - /// \relates GraphReader - /// \relates NodeSetReader - /// \relates EdgeSetReader - /// \relates NodesReader - /// \relates EdgesReader - /// \relates AttributeReader - class LemonReader { - private: - - class FilterStreamBuf : public std::streambuf { - public: - - typedef std::streambuf Parent; - typedef Parent::char_type char_type; - FilterStreamBuf(std::istream& is, int& num) - : _is(is), _base(0), _eptr(0), - _num(num), skip_state(after_endl) {} - - protected: - - enum skip_state_type { - no_skip, - after_endl, - comment_line - }; - - char_type small_buf[1]; - - - std::istream& _is; - - char_type* _base; - char_type* _eptr; - - int& _num; - - skip_state_type skip_state; - - - char_type* base() { return _base; } - - char_type* eptr() { return _eptr; } - - int blen() { return _eptr - _base; } - - void setb(char_type* buf, int len) { - _base = buf; - _eptr = buf + len; - } - - virtual std::streambuf* setbuf(char *buf, int len) { - if (base()) return 0; - if (buf != 0 && len >= (int)sizeof(small_buf)) { - setb(buf, len); - } else { - setb(small_buf, sizeof(small_buf)); - } - setg(0, 0, 0); - return this; - } - - bool put_char(char c) { - switch (skip_state) { - case no_skip: - switch (c) { - case '\n': - skip_state = after_endl; - return true; - default: - return true; - } - case after_endl: - switch (c) { - case '@': - return false; - case '\n': - return false; - case '#': - skip_state = comment_line; - return false; - default: - if (!isspace(c)) { - skip_state = no_skip; - return true; - } else { - return false; - } - } - break; - case comment_line: - switch (c) { - case '\n': - skip_state = after_endl; - return false; - default: - return false; - } - } - return false; - } - - virtual int underflow() { - char c; - if (_is.read(&c, 1)) { - _is.putback(c); - if (c == '@') { - return EOF; - } - } else { - return EOF; - } - char_type *ptr; - for (ptr = base(); ptr != eptr(); ++ptr) { - if (_is.read(&c, 1)) { - if (c == '\n') ++_num; - if (put_char(c)) { - *ptr = c; - } else { - if (skip_state == after_endl && c == '@') { - _is.putback('@'); - break; - } - --ptr; - } - } else { - break; - } - } - setg(base(), base(), ptr); - return *base(); - } - - virtual int sync() { - return EOF; - } - }; - - public: - - /// \brief Abstract base class for reading a section. - /// - /// This class has an \c header() member function what get a - /// header line string and decides if it want to process the next - /// section. Several SectionReaders can be attached to an LemonReader - /// and the first attached what can process the section will be used. - /// Its \c read() member will called with a stream contains the section. - /// From this stream the empty lines and comments are filtered out. - class SectionReader { - friend class LemonReader; - protected: - /// \brief Constructor for SectionReader. - /// - /// Constructor for SectionReader. It attach this reader to - /// the given LemonReader. - SectionReader(LemonReader& reader) { - reader.attach(*this); - } - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the SectionReader can process - /// the section with the given header line. - virtual bool header(const std::string& line) = 0; - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) = 0; - }; - - /// \brief Constructor for LemonReader. - /// - /// Constructor for LemonReader which reads from the given stream. - LemonReader(std::istream& _is) - : is(&_is), own_is(false) {} - - /// \brief Constructor for LemonReader. - /// - /// Constructor for LemonReader which reads from the given file. - LemonReader(const std::string& filename) - : is(0), own_is(true) { - is = new std::ifstream(filename.c_str()); - } - - /// \brief Desctructor for LemonReader. - /// - /// Desctructor for LemonReader. - ~LemonReader() { - if (own_is) { - delete is; - } - } - - private: - LemonReader(const LemonReader&); - void operator=(const LemonReader&); - - void attach(SectionReader& reader) { - readers.push_back(&reader); - } - - public: - /// \brief Executes the LemonReader. - /// - /// It executes the LemonReader. - void run() { - int line_num = 0; - std::string line; - try { - while ((++line_num, getline(*is, line)) && line.find("@end") != 0) { - SectionReaders::iterator it; - for (it = readers.begin(); it != readers.end(); ++it) { - if ((*it)->header(line)) { - char buf[2048]; - FilterStreamBuf buffer(*is, line_num); - buffer.pubsetbuf(buf, sizeof(buf)); - std::istream is(&buffer); - (*it)->read(is); - break; - } - } - } - } catch (DataFormatError& error) { - error.line(line_num); - throw error; - } - } - - - private: - - std::istream* is; - bool own_is; - - typedef std::vector SectionReaders; - SectionReaders readers; - - }; - - /// \brief Helper class for implementing the common SectionReaders. - /// - /// Helper class for implementing the common SectionReaders. - class CommonSectionReaderBase : public LemonReader::SectionReader { - typedef LemonReader::SectionReader Parent; - protected: - - /// \brief Constructor for CommonSectionReaderBase. - /// - /// Constructor for CommonSectionReaderBase. It attach this reader to - /// the given LemonReader. - CommonSectionReaderBase(LemonReader& _reader) - : Parent(_reader) {} - - template - class ReaderBase; - - template - class InverterBase : public ReaderBase<_Item> { - public: - typedef _Item Item; - virtual void read(std::istream&, const Item&) = 0; - virtual Item read(std::istream&) const = 0; - - virtual InverterBase<_Item>* getInverter() { - return this; - } - }; - - template - class MapReaderInverter : public InverterBase<_Item> { - public: - typedef _Item Item; - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef _Map Map; - typedef std::map > Inverse; - - typename SmartReference::Type map; - Reader reader; - Inverse inverse; - - MapReaderInverter(typename SmartParameter::Type _map, - const Reader& _reader) - : map(_map), reader(_reader) {} - - virtual ~MapReaderInverter() {} - - virtual void read(std::istream& is, const Item& item) { - Value value; - reader.read(is, value); - map.set(item, value); - typename Inverse::iterator it = inverse.find(value); - if (it == inverse.end()) { - inverse.insert(std::make_pair(value, item)); - } else { - throw DataFormatError("Multiple ID occurence"); - } - } - - virtual Item read(std::istream& is) const { - Value value; - reader.read(is, value); - typename Inverse::const_iterator it = inverse.find(value); - if (it != inverse.end()) { - return it->second; - } else { - throw DataFormatError("Invalid ID error"); - } - } - }; - - template - class SkipReaderInverter : public InverterBase<_Item> { - public: - typedef _Item Item; - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef std::map > Inverse; - - Reader reader; - - SkipReaderInverter(const Reader& _reader) - : reader(_reader) {} - - virtual ~SkipReaderInverter() {} - - virtual void read(std::istream& is, const Item& item) { - Value value; - reader.read(is, value); - typename Inverse::iterator it = inverse.find(value); - if (it == inverse.end()) { - inverse.insert(std::make_pair(value, item)); - } else { - throw DataFormatError("Multiple ID occurence error"); - } - } - - virtual Item read(std::istream& is) const { - Value value; - reader.read(is, value); - typename Inverse::const_iterator it = inverse.find(value); - if (it != inverse.end()) { - return it->second; - } else { - throw DataFormatError("Invalid ID error"); - } - } - - private: - Inverse inverse; - }; - - template - class ReaderBase { - public: - typedef _Item Item; - - virtual ~ReaderBase() {} - - virtual void read(std::istream& is, const Item& item) = 0; - virtual InverterBase<_Item>* getInverter() = 0; - }; - - template - class MapReader : public ReaderBase<_Item> { - public: - typedef _Map Map; - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef _Item Item; - - typename SmartReference::Type map; - Reader reader; - - MapReader(typename SmartParameter::Type _map, - const Reader& _reader) - : map(_map), reader(_reader) {} - - virtual ~MapReader() {} - - virtual void read(std::istream& is, const Item& item) { - Value value; - reader.read(is, value); - map.set(item, value); - } - - virtual InverterBase<_Item>* getInverter() { - return new MapReaderInverter(map, reader); - } - }; - - - template - class SkipReader : public ReaderBase<_Item> { - public: - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef _Item Item; - - Reader reader; - SkipReader(const Reader& _reader) : reader(_reader) {} - - virtual ~SkipReader() {} - - virtual void read(std::istream& is, const Item&) { - Value value; - reader.read(is, value); - } - - virtual InverterBase* getInverter() { - return new SkipReaderInverter(reader); - } - }; - - template - class IdReaderBase { - public: - typedef _Item Item; - virtual Item read(std::istream& is) const = 0; - }; - - template - class IdReader : public IdReaderBase<_Item> { - public: - typedef _Item Item; - typedef _BoxedIdReader BoxedIdReader; - - const BoxedIdReader& boxedIdReader; - - IdReader(const BoxedIdReader& _boxedIdReader) - : boxedIdReader(_boxedIdReader) {} - - virtual Item read(std::istream& is) const { - return boxedIdReader.readId(is, Item()); - } - }; - - class ValueReaderBase { - public: - virtual void read(std::istream&) {}; - }; - - template - class ValueReader : public ValueReaderBase { - public: - typedef _Value Value; - typedef _Reader Reader; - - ValueReader(Value& _value, const Reader& _reader) - : value(_value), reader(_reader) {} - - virtual void read(std::istream& is) { - reader.read(is, value); - } - private: - Value& value; - Reader reader; - }; - - }; - - /// \ingroup io_group - /// \brief SectionReader for reading a graph's nodeset. - /// - /// The lemon format can store multiple graph nodesets with several maps. - /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the - /// \c nodeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes a node in the nodeset, and - /// contains the mapped values for each map. - /// - /// If the nodeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c readId() member will read a value from the given stream it will - /// give back that node which is mapped to this value. - /// - /// \relates LemonReader - template - class NodeSetReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Traits::Skipper DefaultSkipper; - - /// \brief Constructor. - /// - /// Constructor for NodeSetReader. It creates the NodeSetReader and - /// attach it into the given LemonReader. The nodeset reader will - /// add the readed nodes to the given Graph. The reader will read - /// the section when the \c section_id and the \c _id are the same. - NodeSetReader(LemonReader& _reader, - typename SmartParameter::Type _graph, - const std::string& _id = std::string(), - const DefaultSkipper& _skipper = DefaultSkipper()) - : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} - - - /// \brief Destructor. - /// - /// Destructor for NodeSetReader. - virtual ~NodeSetReader() { - for (typename MapReaders::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - NodeSetReader(const NodeSetReader&); - void operator=(const NodeSetReader&); - - public: - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - NodeSetReader& readNodeMap(std::string name, Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - NodeSetReader& readNodeMap(std::string name, const Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - NodeSetReader& readNodeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readMap::Type> - (name, map, reader); - } - - template - NodeSetReader& readNodeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readMap::Type> - (name, map, reader); - } - - private: - - template - NodeSetReader& _readMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert( - make_pair(name, new MapReader(map, reader))); - return *this; - } - - public: - - /// \brief Add a new node map skipper command for the reader. - /// - /// Add a new node map skipper command for the reader. - template - NodeSetReader& skipNodeMap(std::string name, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, new SkipReader(reader))); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line starts with \c \@nodeset, - /// and the header line's id and the nodeset's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@nodeset" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::vector* > index; - std::string line; - - getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - typename MapReaders::iterator it = readers.find(id); - if (it != readers.end()) { - index.push_back(it->second); - } else { - index.push_back(&skipper); - } - if (id == "id" && inverter.get() == 0) { - inverter.reset(index.back()->getInverter()); - index.back() = inverter.get(); - } - } - while (getline(is, line)) { - Node node = graph.addNode(); - std::istringstream ls(line); - for (int i = 0; i < (int)index.size(); ++i) { - index[i]->read(ls, node); - } - } - } - - public: - - /// \brief Returns true if the nodeset can give back the node by its id. - /// - /// Returns true if the nodeset can give back the node by its id. - /// It is possible only if an "id" named map was read. - bool isIdReader() const { - return inverter.get() != 0; - } - - /// \brief Gives back the node by its id. - /// - /// It reads an id from the stream and gives back which node belongs to - /// it. It is possible only if there was read an "id" named map. - Node readId(std::istream& is, Node = Node()) const { - return inverter->read(is); - } - - private: - - typedef std::map*> MapReaders; - MapReaders readers; - - typename SmartReference::Type graph; - std::string id; - SkipReader skipper; - - std::auto_ptr > inverter; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading a graph's edgeset. - /// - /// The lemon format can store multiple graph edgesets with several maps. - /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the - /// \c edgeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes an edge in the edgeset. The - /// line contains the source and the target nodes' id and the mapped - /// values for each map. - /// - /// If the edgeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c readId() member will read a value from the given stream it will - /// give back that edge which is mapped to this value. - /// - /// The edgeset reader needs a node id reader to identify which nodes - /// have to be connected. If a NodeSetReader reads an "id" named map, - /// it will be able to resolve the nodes by ids. - /// - /// \relates LemonReader - template - class EdgeSetReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Traits::Skipper DefaultSkipper; - - /// \brief Constructor. - /// - /// Constructor for EdgeSetReader. It creates the EdgeSetReader and - /// attach it into the given LemonReader. The edgeset reader will - /// add the readed edges to the given Graph. It will use the given - /// node id reader to read the source and target nodes of the edges. - /// The reader will read the section only if the \c _id and the - /// \c edgset_id are the same. - template - EdgeSetReader(LemonReader& _reader, - typename SmartParameter::Type _graph, - const NodeIdReader& _nodeIdReader, - const std::string& _id = std::string(), - const DefaultSkipper& _skipper = DefaultSkipper()) - : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), - nodeIdReader(new IdReader(_nodeIdReader)) {} - - /// \brief Destructor. - /// - /// Destructor for EdgeSetReader. - virtual ~EdgeSetReader() { - for (typename MapReaders::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - EdgeSetReader(const EdgeSetReader&); - void operator=(const EdgeSetReader&); - - public: - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - EdgeSetReader& readEdgeMap(std::string name, Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - EdgeSetReader& readEdgeMap(std::string name, const Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - EdgeSetReader& readEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readMap::Type>(name, map, reader); - } - - template - EdgeSetReader& readEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readMap::Type>(name, map, reader); - } - - private: - - template - EdgeSetReader& _readMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert( - make_pair(name, new MapReader(map, reader))); - return *this; - } - - public: - - /// \brief Add a new edge map skipper command for the reader. - /// - /// Add a new edge map skipper command for the reader. - template - EdgeSetReader& skipEdgeMap(std::string name, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, new SkipReader(reader))); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line starts with \c \@edgeset, - /// and the header line's id and the edgeset's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@edgeset" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::vector* > index; - std::string line; - - getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - typename MapReaders::iterator it = readers.find(id); - if (it != readers.end()) { - index.push_back(it->second); - } else { - index.push_back(&skipper); - } - if (id == "id" && inverter.get() == 0) { - inverter.reset(index.back()->getInverter()); - index.back() = inverter.get(); - } - } - while (getline(is, line)) { - std::istringstream ls(line); - Node from = nodeIdReader->read(ls); - Node to = nodeIdReader->read(ls); - Edge edge = graph.addEdge(from, to); - for (int i = 0; i < (int)index.size(); ++i) { - index[i]->read(ls, edge); - } - } - } - - public: - - /// \brief Returns true if the edgeset can give back the edge by its id. - /// - /// Returns true if the edgeset can give back the edge by its id. - /// It is possible only if an "id" named map was read. - bool isIdReader() const { - return inverter.get() != 0; - } - - /// \brief Gives back the edge by its id. - /// - /// It reads an id from the stream and gives back which edge belongs to - /// it. It is possible only if there was read an "id" named map. - Edge readId(std::istream& is, Edge = Edge()) const { - return inverter->read(is); - } - - private: - - typedef std::map*> MapReaders; - MapReaders readers; - - typename SmartReference::Type graph; - std::string id; - SkipReader skipper; - - std::auto_ptr > inverter; - std::auto_ptr > nodeIdReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading a undirected graph's edgeset. - /// - /// The lemon format can store multiple undirected edgesets with several - /// maps. The undirected edgeset section's header line is \c \@undiredgeset - /// \c undiredgeset_id, but the \c undiredgeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes an edge in the edgeset. The - /// line contains the connected nodes' id and the mapped values for each map. - /// - /// The section can handle the directed as a syntactical sugar. Two - /// undirected edge map describes one directed edge map. This two maps - /// are the forward map and the backward map and the names of this map - /// is near the same just with a prefix \c '+' or \c '-' character - /// difference. - /// - /// If the edgeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c readId() member will read a value from the given stream it will - /// give back that undiricted edge which is mapped to this value. - /// - /// The undirected edgeset reader needs a node id reader to identify which - /// nodes have to be connected. If a NodeSetReader reads an "id" named map, - /// it will be able to resolve the nodes by ids. - /// - /// \relates LemonReader - template - class UndirEdgeSetReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - typedef typename Traits::Skipper DefaultSkipper; - - /// \brief Constructor. - /// - /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader - /// and attach it into the given LemonReader. The undirected edgeset - /// reader will add the readed undirected edges to the given Graph. It - /// will use the given node id reader to read the source and target - /// nodes of the edges. The reader will read the section only if the - /// \c _id and the \c undiredgset_id are the same. - template - UndirEdgeSetReader(LemonReader& _reader, - typename SmartParameter::Type _graph, - const NodeIdReader& _nodeIdReader, - const std::string& _id = std::string(), - const DefaultSkipper& _skipper = DefaultSkipper()) - : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), - nodeIdReader(new IdReader(_nodeIdReader)) {} - - /// \brief Destructor. - /// - /// Destructor for UndirEdgeSetReader. - virtual ~UndirEdgeSetReader() { - for (typename MapReaders::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - UndirEdgeSetReader(const UndirEdgeSetReader&); - void operator=(const UndirEdgeSetReader&); - - public: - - /// \brief Add a new undirected edge map reader command for the reader. - /// - /// Add a new edge undirected map reader command for the reader. - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new undirected edge map reader command for the reader. - /// - /// Add a new edge undirected map reader command for the reader. - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readMap::Type> - (name, map, reader); - } - - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readMap::Type > - (name, map, reader); - } - - private: - - template - UndirEdgeSetReader& _readMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert( - make_pair(name, new MapReader(map, reader))); - return *this; - } - - public: - - /// \brief Add a new undirected edge map skipper command for the reader. - /// - /// Add a new undirected edge map skipper command for the reader. - template - UndirEdgeSetReader& skipUndirEdgeMap(std::string name, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, - new SkipReader(reader))); - return *this; - } - - /// \brief Add a new directed edge map reader command for the reader. - /// - /// Add a new directed edge map reader command for the reader. - template - UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) { - return _readDirMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) { - return _readDirMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new directed edge map reader command for the reader. - /// - /// Add a new directed edge map reader command for the reader. - template - UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readDirMap::Type> - (name, map, reader); - } - - template - UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readDirMap::Type> - (name, map, reader); - } - - private: - - template - UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - readMap("+" + name, - _reader_bits::writeComposeMap(map, forwardMap(graph)), reader); - readMap("-" + name, - _reader_bits::writeComposeMap(map, backwardMap(graph)), reader); - return *this; - } - - public: - - /// \brief Add a new directed edge map skipper command for the reader. - /// - /// Add a new directed edge map skipper command for the reader. - template - UndirEdgeSetReader& skipEdgeMap(std::string name, - const Reader& reader = Reader()) { - skipMap("+" + name, reader); - skipMap("-" + name, reader); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line starts with \c \@undiredgeset, - /// and the header line's id and the edgeset's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@undiredgeset" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::vector* > index; - std::string line; - - getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - typename MapReaders::iterator it = readers.find(id); - if (it != readers.end()) { - index.push_back(it->second); - } else { - index.push_back(&skipper); - } - if (id == "id" && inverter.get() == 0) { - inverter.reset(index.back()->getInverter()); - index.back() = inverter.get(); - } - } - while (getline(is, line)) { - std::istringstream ls(line); - Node from = nodeIdReader->read(ls); - Node to = nodeIdReader->read(ls); - UndirEdge edge = graph.addEdge(from, to); - for (int i = 0; i < (int)index.size(); ++i) { - index[i]->read(ls, edge); - } - } - } - - public: - - /// \brief Returns true if the edgeset can give back the edge by its id. - /// - /// Returns true if the edgeset can give back the undirected edge by its - /// id. It is possible only if an "id" named map was read. - bool isIdReader() const { - return inverter.get() != 0; - } - - /// \brief Gives back the undirected edge by its id. - /// - /// It reads an id from the stream and gives back which undirected edge - /// belongs to it. It is possible only if there was read an "id" named map. - UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const { - return inverter->read(is); - } - - /// \brief Gives back the directed edge by its id. - /// - /// It reads an id from the stream and gives back which directed edge - /// belongs to it. The directed edge id is the \c '+' or \c '-' character - /// and the undirected edge id. It is possible only if there was read - /// an "id" named map. - Edge readId(std::istream& is, Edge = Edge()) const { - char c; - is >> c; - UndirEdge undirEdge = inverter->read(is); - if (c == '+') { - return graph.edgeWithSource(undirEdge, graph.source(undirEdge)); - } else if (c == '-') { - return graph.edgeWithSource(undirEdge, graph.target(undirEdge)); - } else { - throw DataFormatError("Wrong id format for edge " - "in undirected edgeset"); - } - } - - private: - - typedef std::map*> MapReaders; - MapReaders readers; - - typename SmartReference::Type graph; - std::string id; - SkipReader skipper; - - std::auto_ptr > inverter; - std::auto_ptr > nodeIdReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading labeled nodes. - /// - /// The nodes section's header line is \c \@nodes \c nodes_id, but the - /// \c nodes_id may be empty. - /// - /// Each line in the section contains the name of the node - /// and then the node id. - /// - /// \relates LemonReader - template - class NodeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Graph Graph; - typedef typename Graph::Node Node; - public: - - /// \brief Constructor. - /// - /// Constructor for NodeReader. It creates the NodeReader and - /// attach it into the given LemonReader. It will use the given - /// node id reader to give back the nodes. The reader will read the - /// section only if the \c _id and the \c nodes_id are the same. - template - NodeReader(LemonReader& _reader, const _IdReader& _idReader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id), - idReader(new IdReader(_idReader)) {} - - /// \brief Destructor. - /// - /// Destructor for NodeReader. - virtual ~NodeReader() {} - - private: - NodeReader(const NodeReader&); - void operator=(const NodeReader&); - - public: - - /// \brief Add a node reader command for the NodeReader. - /// - /// Add a node reader command for the NodeReader. - void readNode(const std::string& name, Node& item) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, &item)); - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@nodes, - /// and the header line's id and the reader's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@nodes" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - typename NodeReaders::iterator it = readers.find(id); - if (it != readers.end()) { - *(it->second) = idReader->read(ls); - } - } - } - - private: - - std::string id; - - typedef std::map NodeReaders; - NodeReaders readers; - std::auto_ptr > idReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading labeled edges. - /// - /// The edges section's header line is \c \@edges \c edges_id, but the - /// \c edges_id may be empty. - /// - /// Each line in the section contains the name of the edge - /// and then the edge id. - /// - /// \relates LemonReader - template - class EdgeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Graph Graph; - typedef typename Graph::Edge Edge; - public: - - /// \brief Constructor. - /// - /// Constructor for EdgeReader. It creates the EdgeReader and - /// attach it into the given LemonReader. It will use the given - /// edge id reader to give back the edges. The reader will read the - /// section only if the \c _id and the \c edges_id are the same. - template - EdgeReader(LemonReader& _reader, const _IdReader& _idReader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id), - idReader(new IdReader(_idReader)) {} - - /// \brief Destructor. - /// - /// Destructor for EdgeReader. - virtual ~EdgeReader() {} - private: - EdgeReader(const EdgeReader&); - void operator=(const EdgeReader&); - - public: - - /// \brief Add an edge reader command for the EdgeReader. - /// - /// Add an edge reader command for the EdgeReader. - void readEdge(const std::string& name, Edge& item) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, &item)); - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@edges, - /// and the header line's id and the reader's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@edges" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - typename EdgeReaders::iterator it = readers.find(id); - if (it != readers.end()) { - *(it->second) = idReader->read(ls); - } - } - } - - private: - - std::string id; - - typedef std::map EdgeReaders; - EdgeReaders readers; - std::auto_ptr > idReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading labeled undirected edges. - /// - /// The undirected edges section's header line is \c \@undiredges - /// \c undiredges_id, but the \c undiredges_id may be empty. - /// - /// Each line in the section contains the name of the undirected edge - /// and then the undirected edge id. - /// - /// \relates LemonReader - template - class UndirEdgeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Graph Graph; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - public: - - /// \brief Constructor. - /// - /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and - /// attach it into the given LemonReader. It will use the given - /// undirected edge id reader to give back the edges. The reader will - /// read the section only if the \c _id and the \c undiredges_id are - /// the same. - template - UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id), - undirEdgeIdReader(new IdReader(_idReader)), - edgeIdReader(new IdReader(_idReader)) - {} - - /// \brief Destructor. - /// - /// Destructor for UndirEdgeReader. - virtual ~UndirEdgeReader() {} - private: - UndirEdgeReader(const UndirEdgeReader&); - void operator=(const UndirEdgeReader&); - - public: - - /// \brief Add an undirected edge reader command for the UndirEdgeReader. - /// - /// Add an undirected edge reader command for the UndirEdgeReader. - void readUndirEdge(const std::string& name, UndirEdge& item) { - if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) { - ErrorMessage msg; - msg << "Multiple read rule for undirected edge: " << name; - throw IOParameterError(msg.message()); - } - undirEdgeReaders.insert(make_pair(name, &item)); - } - - /// \brief Add an edge reader command for the UndirEdgeReader. - /// - /// Add an edge reader command for the UndirEdgeReader. - void readEdge(const std::string& name, Edge& item) { - if (edgeReaders.find(name) != edgeReaders.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge: " << name; - throw IOParameterError(msg.message()); - } - edgeReaders.insert(make_pair(name, &item)); - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@edges, - /// and the header line's id and the reader's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@undiredges" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - { - typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id); - if (it != undirEdgeReaders.end()) { - *(it->second) = undirEdgeIdReader->read(ls); - break; - } - } { - typename EdgeReaders::iterator it = edgeReaders.find(id); - if (it != edgeReaders.end()) { - *(it->second) = edgeIdReader->read(ls); - break; - } - } - } - } - - private: - - std::string id; - - typedef std::map UndirEdgeReaders; - UndirEdgeReaders undirEdgeReaders; - std::auto_ptr > undirEdgeIdReader; - - typedef std::map EdgeReaders; - EdgeReaders edgeReaders; - std::auto_ptr > edgeIdReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for attributes. - /// - /// The lemon format can store multiple attribute set. Each set has - /// the header line \c \@attributes \c attributeset_id, but the - /// attributeset_id may be empty. - /// - /// The attributeset section contains several lines. Each of them starts - /// with an attribute and then a the value for the id. - /// - /// \relates LemonReader - template - class AttributeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Traits Traits; - public: - /// \brief Constructor. - /// - /// Constructor for AttributeReader. It creates the AttributeReader and - /// attach it into the given LemonReader. The reader process a section - /// only if the \c section_id and the \c _id are the same. - AttributeReader(LemonReader& _reader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id) {} - - /// \brief Destructor. - /// - /// Destructor for AttributeReader. - virtual ~AttributeReader() { - for (typename Readers::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - AttributeReader(const AttributeReader&); - void operator=(AttributeReader&); - - public: - /// \brief Add an attribute reader command for the reader. - /// - /// Add an attribute reader command for the reader. - template - AttributeReader& readAttribute(const std::string& id, Value& value) { - return readAttribute > - (id, value); - } - - /// \brief Add an attribute reader command for the reader. - /// - /// Add an attribute reader command for the reader. - template - AttributeReader& readAttribute(const std::string& name, Value& value, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for attribute: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, new ValueReader - (value, reader))); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@attributes, - /// and the header line's id and the attributeset's id are the same. - bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@attributes" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - typename Readers::iterator it = readers.find(id); - if (it != readers.end()) { - it->second->read(ls); - } - } - } - - private: - std::string id; - - typedef std::map Readers; - Readers readers; - }; - - /// \ingroup io_group - /// \brief SectionReader for retrieve what is in the file. - /// - /// SectionReader for retrieve what is in the file. If you want - /// to know which sections, maps and items are in the file - /// use the next code: - /// \code - /// LemonReader reader("input.lgf"); - /// ContentReader content(reader); - /// reader.run(); - /// \endcode - class ContentReader : public LemonReader::SectionReader { - typedef LemonReader::SectionReader Parent; - public: - /// \brief Constructor. - /// - /// Constructor for - ContentReader(LemonReader& _reader) : Parent(_reader) {} - - /// \brief Desctructor. - /// - /// Desctructor. - virtual ~ContentReader() {} - - /// \brief Gives back how many nodesets are in the file. - /// - /// Gives back how many nodesets are in the file. - int nodeSetNum() const { - return nodesets.size(); - } - - /// \brief Gives back the name of nodeset on the indiced position. - /// - /// Gives back the name of nodeset on the indiced position. - std::string nodeSetName(int index) const { - return nodesets[index].name; - } - - /// \brief Gives back the map names of nodeset on the indiced position. - /// - /// Gives back the map names of nodeset on the indiced position. - const std::vector& nodeSetMaps(int index) const { - return nodesets[index].items; - } - - /// \brief Gives back how many edgesets are in the file. - /// - /// Gives back how many edgesets are in the file. - int edgeSetNum() const { - return edgesets.size(); - } - - /// \brief Gives back the name of edgeset on the indiced position. - /// - /// Gives back the name of edgeset on the indiced position. - std::string edgeSetName(int index) const { - return edgesets[index].name; - } - - /// \brief Gives back the map names of edgeset on the indiced position. - /// - /// Gives back the map names of edgeset on the indiced position. - const std::vector& edgeSetMaps(int index) const { - return edgesets[index].items; - } - - /// \brief Gives back how many undirected edgesets are in the file. - /// - /// Gives back how many undirected edgesets are in the file. - int undirEdgeSetNum() const { - return undiredgesets.size(); - } - - /// \brief Gives back the name of undirected edgeset on the indiced - /// position. - /// - /// Gives back the name of undirected edgeset on the indiced position. - std::string undirEdgeSetName(int index) const { - return undiredgesets[index].name; - } - - /// \brief Gives back the map names of undirected edgeset on the indiced - /// position. - /// - /// Gives back the map names of undirected edgeset on the indiced position. - const std::vector& undirEdgeSetMaps(int index) const { - return undiredgesets[index].items; - } - - /// \brief Gives back how many labeled nodes section are in the file. - /// - /// Gives back how many labeled nodes section are in the file. - int nodesNum() const { - return nodes.size(); - } - - /// \brief Gives back the name of labeled nodes section on the indiced - /// position. - /// - /// Gives back the name of labeled nodes section on the indiced position. - std::string nodesName(int index) const { - return nodes[index].name; - } - - /// \brief Gives back the names of the labeled nodes in the indiced - /// section. - /// - /// Gives back the names of the labeled nodes in the indiced section. - const std::vector& nodesItems(int index) const { - return nodes[index].items; - } - - /// \brief Gives back how many labeled edges section are in the file. - /// - /// Gives back how many labeled edges section are in the file. - int edgesNum() const { - return edges.size(); - } - - /// \brief Gives back the name of labeled edges section on the indiced - /// position. - /// - /// Gives back the name of labeled edges section on the indiced position. - std::string edgesName(int index) const { - return edges[index].name; - } - - /// \brief Gives back the names of the labeled edges in the indiced - /// section. - /// - /// Gives back the names of the labeled edges in the indiced section. - const std::vector& edgesItems(int index) const { - return edges[index].items; - } - - /// \brief Gives back how many labeled undirected edges section are - /// in the file. - /// - /// Gives back how many labeled undirected edges section are in the file. - int undirEdgesNum() const { - return undiredges.size(); - } - - /// \brief Gives back the name of labeled undirected edges section - /// on the indiced position. - /// - /// Gives back the name of labeled undirected edges section on the - /// indiced position. - std::string undirEdgesName(int index) const { - return undiredges[index].name; - } - - /// \brief Gives back the names of the labeled undirected edges in - /// the indiced section. - /// - /// Gives back the names of the labeled undirected edges in the - /// indiced section. - const std::vector& undirEdgesItems(int index) const { - return undiredges[index].items; - } - - - /// \brief Gives back how many attributes section are in the file. - /// - /// Gives back how many attributes section are in the file. - int attributesNum() const { - return attributes.size(); - } - - /// \brief Gives back the name of attributes section on the indiced - /// position. - /// - /// Gives back the name of attributes section on the indiced position. - std::string attributesName(int index) const { - return attributes[index].name; - } - - /// \brief Gives back the names of the attributes in the indiced section. - /// - /// Gives back the names of the attributes in the indiced section. - const std::vector& attributesItems(int index) const { - return attributes[index].items; - } - - const std::vector& otherSections() const { - return sections; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the section is common section. - bool header(const std::string& line) { - std::istringstream ls(line); - std::string command, name; - ls >> command >> name; - if (command == "@nodeset") { - current = command; - nodesets.push_back(SectionInfo(name)); - } else if (command == "@edgeset") { - current = command; - edgesets.push_back(SectionInfo(name)); - } else if (command == "@undiredgeset") { - current = command; - undiredgesets.push_back(SectionInfo(name)); - } else if (command == "@nodes") { - current = command; - nodes.push_back(SectionInfo(name)); - } else if (command == "@edges") { - current = command; - edges.push_back(SectionInfo(name)); - } else if (command == "@undiredges") { - current = command; - undiredges.push_back(SectionInfo(name)); - } else if (command == "@attributes") { - current = command; - attributes.push_back(SectionInfo(name)); - } else { - sections.push_back(line); - return false; - } - return true; - } - - /// \brief Retrieve the items from various sections. - /// - /// Retrieve the items from various sections. - void read(std::istream& is) { - if (current == "@nodeset") { - readMapNames(is, nodesets.back().items); - } else if (current == "@edgeset") { - readMapNames(is, edgesets.back().items); - } else if (current == "@undiredgeset") { - readMapNames(is, undiredgesets.back().items); - } else if (current == "@nodes") { - readItemNames(is, nodes.back().items); - } else if (current == "@edges") { - readItemNames(is, edges.back().items); - } else if (current == "@undiredges") { - readItemNames(is, undiredges.back().items); - } else if (current == "@attributes") { - readItemNames(is, attributes.back().items); - } - } - - private: - - void readMapNames(std::istream& is, std::vector& maps) { - std::string line, id; - std::getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - maps.push_back(id); - } - while (getline(is, line)); - } - - void readItemNames(std::istream& is, std::vector& maps) { - std::string line, id; - while (std::getline(is, line)) { - std::istringstream ls(line); - ls >> id; - maps.push_back(id); - } - } - - struct SectionInfo { - std::string name; - std::vector items; - - SectionInfo(const std::string& _name) : name(_name) {} - }; - - std::vector nodesets; - std::vector edgesets; - std::vector undiredgesets; - - std::vector nodes; - std::vector edges; - std::vector undiredges; - - std::vector attributes; - - std::vector sections; - - std::string current; - - }; - -} -#endif