# HG changeset patch # User deba # Date 1188309642 0 # Node ID 2025a571895ece0faf370d4e63ff395606472151 # Parent feb7974cf4ec9832c709bb1a1fea1034f12a0f7f PathNodeIt PathWriter/Reader structures Distinict MapSet readers and writers diff -r feb7974cf4ec -r 2025a571895e lemon/bits/path_dump.h --- a/lemon/bits/path_dump.h Tue Aug 28 13:58:54 2007 +0000 +++ b/lemon/bits/path_dump.h Tue Aug 28 14:00:42 2007 +0000 @@ -54,7 +54,9 @@ RevEdgeIt() {} RevEdgeIt(Invalid) : path(0), current(INVALID) {} RevEdgeIt(const PredMapPath& _path) - : path(&_path), current(_path.target) {} + : path(&_path), current(_path.target) { + if (path->predMap[current] == INVALID) current = INVALID; + } operator const typename Graph::Edge() const { return path->predMap[current]; @@ -126,7 +128,10 @@ RevEdgeIt() {} RevEdgeIt(Invalid) : path(0), current(INVALID) {} RevEdgeIt(const PredMatrixMapPath& _path) - : path(&_path), current(_path.target) {} + : path(&_path), current(_path.target) { + if (path->predMatrixMap(path->source, current) == INVALID) + current = INVALID; + } operator const typename Graph::Edge() const { return path->predMatrixMap(path->source, current); diff -r feb7974cf4ec -r 2025a571895e lemon/graph_reader.h --- a/lemon/graph_reader.h Tue Aug 28 13:58:54 2007 +0000 +++ b/lemon/graph_reader.h Tue Aug 28 14:00:42 2007 +0000 @@ -324,7 +324,7 @@ /// It reads an label from the stream and gives back which edge belongs to /// it. It is possible only if there was read a "label" named edge map. void readLabel(std::istream& is, Edge& edge) const { - return edgeset_reader.readLabel(is, edge); + edgeset_reader.readLabel(is, edge); } private: @@ -443,10 +443,10 @@ const DefaultSkipper& _skipper = DefaultSkipper()) : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), - u_edgeset_reader(*reader, _graph, nodeset_reader, + uedgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), - u_edge_reader(*reader, u_edgeset_reader, std::string()), + uedge_reader(*reader, uedgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Construct a new UGraphReader. @@ -458,10 +458,10 @@ : reader(new LemonReader(_filename)), own_reader(true), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), - u_edgeset_reader(*reader, _graph, nodeset_reader, + uedgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), - u_edge_reader(*reader, u_edgeset_reader, std::string()), + uedge_reader(*reader, uedgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Construct a new UGraphReader. @@ -472,10 +472,10 @@ const DefaultSkipper& _skipper = DefaultSkipper()) : reader(_reader), own_reader(false), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), - u_edgeset_reader(*reader, _graph, nodeset_reader, + uedgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), - u_edge_reader(*reader, u_edgeset_reader, std::string()), + uedge_reader(*reader, uedgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Destruct the graph reader. @@ -533,13 +533,13 @@ /// Give a new undirected edge map reading command to the reader. template UGraphReader& readUEdgeMap(std::string name, Map& map) { - u_edgeset_reader.readUEdgeMap(name, map); + uedgeset_reader.readUEdgeMap(name, map); return *this; } template UGraphReader& readUEdgeMap(std::string name, const Map& map) { - u_edgeset_reader.readUEdgeMap(name, map); + uedgeset_reader.readUEdgeMap(name, map); return *this; } @@ -550,14 +550,14 @@ template UGraphReader& readUEdgeMap(std::string name, Map& map, const ItemReader& ir = ItemReader()) { - u_edgeset_reader.readUEdgeMap(name, map, ir); + uedgeset_reader.readUEdgeMap(name, map, ir); return *this; } template UGraphReader& readUEdgeMap(std::string name, const Map& map, const ItemReader& ir = ItemReader()) { - u_edgeset_reader.readUEdgeMap(name, map, ir); + uedgeset_reader.readUEdgeMap(name, map, ir); return *this; } @@ -567,7 +567,7 @@ template UGraphReader& skipUEdgeMap(std::string name, const ItemReader& ir = ItemReader()) { - u_edgeset_reader.skipUMap(name, ir); + uedgeset_reader.skipUMap(name, ir); return *this; } @@ -577,13 +577,13 @@ /// Give a new edge map reading command to the reader. template UGraphReader& readEdgeMap(std::string name, Map& map) { - u_edgeset_reader.readEdgeMap(name, map); + uedgeset_reader.readEdgeMap(name, map); return *this; } template UGraphReader& readEdgeMap(std::string name, const Map& map) { - u_edgeset_reader.readEdgeMap(name, map); + uedgeset_reader.readEdgeMap(name, map); return *this; } @@ -594,14 +594,14 @@ template UGraphReader& readEdgeMap(std::string name, Map& map, const ItemReader& ir = ItemReader()) { - u_edgeset_reader.readEdgeMap(name, map, ir); + uedgeset_reader.readEdgeMap(name, map, ir); return *this; } template UGraphReader& readEdgeMap(std::string name, const Map& map, const ItemReader& ir = ItemReader()) { - u_edgeset_reader.readEdgeMap(name, map, ir); + uedgeset_reader.readEdgeMap(name, map, ir); return *this; } @@ -611,7 +611,7 @@ template UGraphReader& skipEdgeMap(std::string name, const ItemReader& ir = ItemReader()) { - u_edgeset_reader.skipEdgeMap(name, ir); + uedgeset_reader.skipEdgeMap(name, ir); return *this; } @@ -627,7 +627,7 @@ /// /// Give a new labeled edge reading command to the reader. UGraphReader& readEdge(std::string name, Edge& edge) { - u_edge_reader.readEdge(name, edge); + uedge_reader.readEdge(name, edge); } /// \brief Give a new labeled undirected edge reading command to the @@ -635,7 +635,7 @@ /// /// Give a new labeled undirected edge reading command to the reader. UGraphReader& readUEdge(std::string name, UEdge& edge) { - u_edge_reader.readUEdge(name, edge); + uedge_reader.readUEdge(name, edge); } /// \brief Give a new attribute reading command. @@ -677,10 +677,10 @@ /// \brief Returns true if the reader can give back the items by its label. /// - /// \brief Returns true if the reader can give back the items by its label. + /// Returns true if the reader can give back the items by its label. bool isLabelReader() const { return nodeset_reader.isLabelReader() && - u_edgeset_reader.isLabelReader(); + uedgeset_reader.isLabelReader(); } /// \brief Gives back the node by its label. @@ -696,7 +696,7 @@ /// It reads an label from the stream and gives back which edge belongs to /// it. It is possible only if there was read a "label" named edge map. void readLabel(std::istream& is, Edge& edge) const { - return u_edgeset_reader.readLabel(is, edge); + return uedgeset_reader.readLabel(is, edge); } /// \brief Gives back the undirected edge by its label. @@ -705,7 +705,7 @@ /// belongs to it. It is possible only if there was read a "label" named /// edge map. void readLabel(std::istream& is, UEdge& uedge) const { - return u_edgeset_reader.readLabel(is, uedge); + return uedgeset_reader.readLabel(is, uedge); } @@ -717,10 +717,10 @@ DefaultSkipper skipper; NodeSetReader nodeset_reader; - UEdgeSetReader u_edgeset_reader; + UEdgeSetReader uedgeset_reader; NodeReader node_reader; - UEdgeReader u_edge_reader; + UEdgeReader uedge_reader; AttributeReader attribute_reader; }; diff -r feb7974cf4ec -r 2025a571895e lemon/graph_writer.h --- a/lemon/graph_writer.h Tue Aug 28 13:58:54 2007 +0000 +++ b/lemon/graph_writer.h Tue Aug 28 14:00:42 2007 +0000 @@ -251,9 +251,17 @@ writer->run(); } + /// \brief Returns true if the writer can give back the labels by the items. + /// + /// Returns true if the writer can give back the the labels by the items. + bool isLabelWriter() const { + return nodeset_writer.isLabelWriter() && + edgeset_writer.isLabelWriter(); + } + /// \brief Write the label of the given node. /// - /// It writes the label of the given node. If there was written an "label" + /// It writes the label of the given node. If there was written a "label" /// named node map then it will write the map value belonging to the node. void writeLabel(std::ostream& os, const Node& item) const { nodeset_writer.writeLabel(os, item); @@ -261,12 +269,32 @@ /// \brief Write the label of the given edge. /// - /// It writes the label of the given edge. If there was written an "label" + /// It writes the label of the given edge. If there was written a "label" /// named edge map then it will write the map value belonging to the edge. void writeLabel(std::ostream& os, const Edge& item) const { edgeset_writer.writeLabel(os, item); } + /// \brief Sorts the given node vector by label. + /// + /// Sorts the given node vector by label. If there was written an + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& nodes) const { + nodeset_writer.sortByLabel(nodes); + } + + /// \brief Sorts the given edge vector by label. + /// + /// Sorts the given edge vector by label. If there was written an + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& edges) const { + edgeset_writer.sortByLabel(edges); + } + private: LemonWriter* writer; @@ -370,9 +398,9 @@ UGraphWriter(std::ostream& _os, const Graph& _graph) : writer(new LemonWriter(_os)), own_writer(true), nodeset_writer(*writer, _graph, std::string()), - u_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + uedgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), - u_edge_writer(*writer, u_edgeset_writer, std::string()), + uedge_writer(*writer, uedgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Construct a new UGraphWriter. @@ -382,21 +410,21 @@ UGraphWriter(const std::string& _filename, const Graph& _graph) : writer(new LemonWriter(_filename)), own_writer(true), nodeset_writer(*writer, _graph, std::string()), - u_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + uedgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), - u_edge_writer(*writer, u_edgeset_writer, std::string()), + uedge_writer(*writer, uedgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Construct a new UGraphWriter. /// /// Construct a new UGraphWriter. It writes the given graph - /// to given LemonReader. + /// to given LemonWriter. UGraphWriter(LemonWriter& _writer, const Graph& _graph) : writer(_writer), own_writer(false), nodeset_writer(*writer, _graph, std::string()), - u_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + uedgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), - u_edge_writer(*writer, u_edgeset_writer, std::string()), + uedge_writer(*writer, uedgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Destruct the graph writer. @@ -434,7 +462,7 @@ /// the writer. template UGraphWriter& writeEdgeMap(std::string label, const Map& map) { - u_edgeset_writer.writeEdgeMap(label, map); + uedgeset_writer.writeEdgeMap(label, map); return *this; } @@ -445,7 +473,7 @@ template UGraphWriter& writeEdgeMap(std::string label, const Map& map, const ItemWriter& iw = ItemWriter()) { - u_edgeset_writer.writeEdgeMap(label, map, iw); + uedgeset_writer.writeEdgeMap(label, map, iw); return *this; } @@ -455,7 +483,7 @@ /// command to the writer. template UGraphWriter& writeUEdgeMap(std::string label, const Map& map) { - u_edgeset_writer.writeUEdgeMap(label, map); + uedgeset_writer.writeUEdgeMap(label, map); return *this; } @@ -466,7 +494,7 @@ template UGraphWriter& writeUEdgeMap(std::string label, const Map& map, const ItemWriter& iw = ItemWriter()) { - u_edgeset_writer.writeUEdgeMap(label, map, iw); + uedgeset_writer.writeUEdgeMap(label, map, iw); return *this; } @@ -484,7 +512,7 @@ /// This function issues a new labeled edge writing /// command to the writer. UGraphWriter& writeEdge(std::string label, const Edge& edge) { - u_edge_writer.writeEdge(label, edge); + uedge_writer.writeEdge(label, edge); } /// \brief Issue a new labeled undirected edge writing command to @@ -493,7 +521,7 @@ /// Issue a new labeled undirected edge writing command to /// the writer. UGraphWriter& writeUEdge(std::string label, const UEdge& edge) { - u_edge_writer.writeUEdge(label, edge); + uedge_writer.writeUEdge(label, edge); } /// \brief Issue a new attribute writing command. @@ -534,9 +562,17 @@ writer->run(); } + /// \brief Returns true if the writer can give back the labels by the items. + /// + /// Returns true if the writer can give back the the labels by the items. + bool isLabelWriter() const { + return nodeset_writer.isLabelWriter() && + uedgeset_writer.isLabelWriter(); + } + /// \brief Write the label of the given node. /// - /// It writes the label of the given node. If there was written an "label" + /// It writes the label of the given node. If there was written a "label" /// named node map then it will write the map value belonging to the node. void writeLabel(std::ostream& os, const Node& item) const { nodeset_writer.writeLabel(os, item); @@ -544,21 +580,50 @@ /// \brief Write the label of the given edge. /// - /// It writes the label of the given edge. If there was written an "label" + /// It writes the label of the given edge. If there was written a "label" /// named edge map then it will write the map value belonging to the edge. void writeLabel(std::ostream& os, const Edge& item) const { - u_edgeset_writer.writeLabel(os, item); + uedgeset_writer.writeLabel(os, item); } /// \brief Write the label of the given undirected edge. /// /// It writes the label of the given undirected edge. If there was - /// written an "label" named edge map then it will write the map + /// written a "label" named edge map then it will write the map /// value belonging to the edge. void writeLabel(std::ostream& os, const UEdge& item) const { - u_edgeset_writer.writeLabel(os, item); + uedgeset_writer.writeLabel(os, item); } + /// \brief Sorts the given node vector by label. + /// + /// Sorts the given node vector by label. If there was written an + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& nodes) const { + nodeset_writer.sortByLabel(nodes); + } + + /// \brief Sorts the given edge vector by label. + /// + /// Sorts the given edge vector by label. If there was written an + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& edges) const { + uedgeset_writer.sortByLabel(edges); + } + + /// \brief Sorts the given undirected edge vector by label. + /// + /// Sorts the given undirected edge vector by label. If there was + /// written an "label" named map then the vector will be sorted by + /// the values of this map. Otherwise if the \c forceLabel + /// parameter was true it will be sorted by its id in the graph. + void sortByLabel(std::vector& uedges) const { + uedgeset_writer.sortByLabel(uedges); + } private: @@ -566,10 +631,10 @@ bool own_writer; NodeSetWriter nodeset_writer; - UEdgeSetWriter u_edgeset_writer; + UEdgeSetWriter uedgeset_writer; NodeWriter node_writer; - UEdgeWriter u_edge_writer; + UEdgeWriter uedge_writer; AttributeWriter attribute_writer; }; diff -r feb7974cf4ec -r 2025a571895e lemon/lemon_reader.h --- a/lemon/lemon_reader.h Tue Aug 28 13:58:54 2007 +0000 +++ b/lemon/lemon_reader.h Tue Aug 28 14:00:42 2007 +0000 @@ -58,7 +58,7 @@ return p < q; } }; - + template class ItemLabelReader { public: @@ -255,7 +255,7 @@ return it->second; } else { ErrorMessage msg; - msg << "Invalid label error: " << value; + msg << "Invalid label error"; throw DataFormatError(msg.message()); } } @@ -289,7 +289,7 @@ virtual Item read(std::istream& is) const { Value value; - reader.read(is, value); + reader.read(is, value); typename Inverse::const_iterator it = inverse.find(value); if (it != inverse.end()) { return it->second; @@ -382,6 +382,7 @@ virtual ~LabelReaderBase() {} virtual Item read(std::istream& is) const = 0; virtual bool isLabelReader() const = 0; + virtual LabelReaderBase<_Item>* clone() const = 0; }; template @@ -390,19 +391,23 @@ typedef _Item Item; typedef _BoxedLabelReader BoxedLabelReader; - const BoxedLabelReader& boxedLabelReader; - - LabelReader(const BoxedLabelReader& _boxedLabelReader) - : boxedLabelReader(_boxedLabelReader) {} + const BoxedLabelReader& labelReader; + + LabelReader(const BoxedLabelReader& _labelReader) + : labelReader(_labelReader) {} virtual Item read(std::istream& is) const { Item item; - boxedLabelReader.readLabel(is, item); + labelReader.readLabel(is, item); return item; } virtual bool isLabelReader() const { - return boxedLabelReader.isLabelReader(); + return labelReader.isLabelReader(); + } + + LabelReader* clone() const { + return new LabelReader(labelReader); } }; @@ -723,7 +728,6 @@ it->second = true; char buf[2048]; FilterStreamBuf buffer(*is, line_num); - try { buffer.pubsetbuf(buf, sizeof(buf)); std::istream ss(&buffer); @@ -1511,8 +1515,8 @@ /// /// 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 "label" named map. - void readLabel(std::istream& is, UEdge& uEdge) const { - uEdge = inverter->read(is); + void readLabel(std::istream& is, UEdge& uedge) const { + uedge = inverter->read(is); } /// \brief Gives back the directed edge by its label. @@ -1524,11 +1528,11 @@ void readLabel(std::istream& is, Edge& edge) const { char c; is >> c; - UEdge uEdge = inverter->read(is); + UEdge uedge = inverter->read(is); if (c == '+') { - edge = graph.direct(uEdge, true); + edge = graph.direct(uedge, true); } else if (c == '-') { - edge = graph.direct(uEdge, false); + edge = graph.direct(uedge, false); } else { throw DataFormatError("Wrong id format for edge " "in undirected edgeset"); @@ -1807,10 +1811,10 @@ : Parent(_reader), name(_name) { checkConcept<_reader_bits::ItemLabelReader, _LabelReader>(); checkConcept<_reader_bits::ItemLabelReader, _LabelReader>(); - uEdgeLabelReader.reset(new _reader_bits:: - LabelReader(_labelReader)); + uedgeLabelReader.reset(new _reader_bits:: + LabelReader(_labelReader)); edgeLabelReader.reset(new _reader_bits:: - LabelReader(_labelReader)); + LabelReader(_labelReader)); } /// \brief Destructor. @@ -1827,12 +1831,12 @@ /// /// Add an undirected edge reader command for the UEdgeReader. void readUEdge(std::string label, UEdge& item) { - if (uEdgeReaders.find(label) != uEdgeReaders.end()) { + if (uedgeReaders.find(label) != uedgeReaders.end()) { ErrorMessage msg; msg << "Multiple read rule for undirected edge: " << label; throw IoParameterError(msg.message()); } - uEdgeReaders.insert(make_pair(label, _reader_bits:: + uedgeReaders.insert(make_pair(label, _reader_bits:: ItemStore(item))); } @@ -1870,7 +1874,7 @@ if (!edgeLabelReader->isLabelReader()) { throw DataFormatError("Cannot find undirected edgeset or label map"); } - if (!uEdgeLabelReader->isLabelReader()) { + if (!uedgeLabelReader->isLabelReader()) { throw DataFormatError("Cannot find undirected edgeset or label map"); } std::string line; @@ -1879,9 +1883,9 @@ std::string id; ls >> id; { - typename UEdgeReaders::iterator it = uEdgeReaders.find(id); - if (it != uEdgeReaders.end()) { - it->second.read(uEdgeLabelReader->read(ls)); + typename UEdgeReaders::iterator it = uedgeReaders.find(id); + if (it != uedgeReaders.end()) { + it->second.read(uedgeLabelReader->read(ls)); it->second.touch(); continue; } @@ -1902,8 +1906,8 @@ throw IoParameterError(msg.message()); } } - for (typename UEdgeReaders::iterator it = uEdgeReaders.begin(); - it != uEdgeReaders.end(); ++it) { + for (typename UEdgeReaders::iterator it = uedgeReaders.begin(); + it != uedgeReaders.end(); ++it) { if (!it->second.touched()) { ErrorMessage msg; msg << "UEdge not found in file: " << it->first; @@ -1913,7 +1917,7 @@ } virtual void missing() { - if (edgeReaders.empty() && uEdgeReaders.empty()) return; + if (edgeReaders.empty() && uedgeReaders.empty()) return; ErrorMessage msg; msg << "UEdges section not found in file: @uedges " << name; throw IoParameterError(msg.message()); @@ -1925,8 +1929,8 @@ typedef std::map > UEdgeReaders; - UEdgeReaders uEdgeReaders; - std::auto_ptr<_reader_bits::LabelReaderBase > uEdgeLabelReader; + UEdgeReaders uedgeReaders; + std::auto_ptr<_reader_bits::LabelReaderBase > uedgeLabelReader; typedef std::map > EdgeReaders; EdgeReaders edgeReaders; @@ -2054,6 +2058,671 @@ }; /// \ingroup section_io + /// \brief SectionReader for reading extra node maps. + /// + /// The lemon format can store maps in the nodeset sections. This + /// class let you make distinict section to store maps. The main + /// purpose of this class is a logical separation of some maps. The + /// other useful application could be to store paths in node maps. + /// + /// The first line of the section contains the names of the maps + /// separated with white spaces. Each next line describes an item + /// in the itemset, and contains in the first column the label of + /// the item and then the mapped values for each map. + /// + /// \relates LemonReader + template + class NodeMapReader : public LemonReader::SectionReader { + typedef LemonReader::SectionReader Parent; + public: + + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef _Traits Traits; + typedef typename Traits::Skipper DefaultSkipper; + + /// \brief Constructor. + /// + /// Constructor for NodeMapReader. It creates the NodeMapReader and + /// attach it into the given LemonReader. The reader will read + /// the section when the \c section_name and the \c _name are the same. + template + NodeMapReader(LemonReader& _reader, + const Graph& _graph, + const _LabelReader& _labelReader, + const std::string& _name = std::string(), + const DefaultSkipper& _skipper = DefaultSkipper()) + : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { + labelReader.reset(new _reader_bits:: + LabelReader(_labelReader)); + } + + + /// \brief Destructor. + /// + /// Destructor for NodeMapReader. + virtual ~NodeMapReader() { + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + delete it->second; + } + } + + private: + NodeMapReader(const NodeMapReader&); + void operator=(const NodeMapReader&); + + public: + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + NodeMapReader& readNodeMap(std::string label, Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, map); + } + + template + NodeMapReader& readNodeMap(std::string label, const Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, map); + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + NodeMapReader& readNodeMap(std::string label, Map& map, + const ItemReader& ir = ItemReader()) { + return _readMap::Type> + (label, map, ir); + } + + template + NodeMapReader& readNodeMap(std::string label, const Map& map, + const ItemReader& ir = ItemReader()) { + return _readMap::Type> + (label, map, ir); + } + + private: + + template + NodeMapReader& _readMap(std::string label, MapParameter map, + const ItemReader& ir = ItemReader()) { + checkConcept, Map>(); + checkConcept<_reader_bits::ItemReader, ItemReader>(); + if (readers.find(label) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for map: " << label; + throw IoParameterError(msg.message()); + } + readers.insert( + make_pair(label, new _reader_bits:: + MapReader(map, ir))); + 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 + NodeMapReader& skipNodeMap(std::string label, + const ItemReader& ir = ItemReader()) { + if (readers.find(label) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for map: " << label; + throw IoParameterError(msg.message()); + } + readers.insert(make_pair(label, new _reader_bits:: + SkipReader(ir))); + 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 \@mapset, + /// and the header line's name and the mapset's name are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string id; + ls >> command >> id; + return command == "@nodemaps" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::vector<_reader_bits::MapReaderBase* > index; + std::string line; + + { + getline(is, line); + std::istringstream ls(line); + std::string id; + while (ls >> id) { + typename MapReaders::iterator it = readers.find(id); + if (it != readers.end()) { + it->second->touch(); + index.push_back(it->second); + } else { + index.push_back(&skipper); + } + } + } + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + if (!it->second->touched()) { + ErrorMessage msg; + msg << "Map not found in file: " << it->first; + throw IoParameterError(msg.message()); + } + } + while (getline(is, line)) { + std::istringstream ls(line); + Node node = labelReader->read(ls); + for (int i = 0; i < int(index.size()); ++i) { + index[i]->read(ls, node); + } + } + } + + virtual void missing() { + if (readers.empty()) return; + ErrorMessage msg; + msg << "NodeMap section not found in file: @nodemaps " << name; + throw IoParameterError(msg.message()); + } + + private: + + typedef std::map*> MapReaders; + MapReaders readers; + + const Graph& graph; + std::string name; + _reader_bits::SkipReader skipper; + std::auto_ptr<_reader_bits::LabelReaderBase > labelReader; + + }; + + /// \ingroup section_io + /// \brief SectionReader for reading extra edge maps. + /// + /// The lemon format can store maps in the edgeset sections. This + /// class let you make distinict section to store maps. The main + /// purpose of this class is a logical separation of some maps. The + /// other useful application could be to store paths in edge maps. + /// + /// The first line of the section contains the names of the maps + /// separated with white spaces. Each next line describes an item + /// in the itemset, and contains in the first column the label of + /// the item and then the mapped values for each map. + /// + /// \relates LemonReader + template + class EdgeMapReader : public LemonReader::SectionReader { + typedef LemonReader::SectionReader Parent; + public: + + typedef _Graph Graph; + typedef typename Graph::Edge Edge; + typedef _Traits Traits; + typedef typename Traits::Skipper DefaultSkipper; + + /// \brief Constructor. + /// + /// Constructor for EdgeMapReader. It creates the EdgeMapReader and + /// attach it into the given LemonReader. The reader will read + /// the section when the \c section_name and the \c _name are the same. + template + EdgeMapReader(LemonReader& _reader, + const Graph& _graph, + const _LabelReader& _labelReader, + const std::string& _name = std::string(), + const DefaultSkipper& _skipper = DefaultSkipper()) + : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { + labelReader.reset(new _reader_bits:: + LabelReader(_labelReader)); + } + + + /// \brief Destructor. + /// + /// Destructor for EdgeMapReader. + virtual ~EdgeMapReader() { + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + delete it->second; + } + } + + private: + EdgeMapReader(const EdgeMapReader&); + void operator=(const EdgeMapReader&); + + public: + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + EdgeMapReader& readEdgeMap(std::string label, Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, map); + } + + template + EdgeMapReader& readEdgeMap(std::string label, const Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, map); + } + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + EdgeMapReader& readEdgeMap(std::string label, Map& map, + const ItemReader& ir = ItemReader()) { + return _readMap::Type> + (label, map, ir); + } + + template + EdgeMapReader& readEdgeMap(std::string label, const Map& map, + const ItemReader& ir = ItemReader()) { + return _readMap::Type> + (label, map, ir); + } + + private: + + template + EdgeMapReader& _readMap(std::string label, MapParameter map, + const ItemReader& ir = ItemReader()) { + checkConcept, Map>(); + checkConcept<_reader_bits::ItemReader, ItemReader>(); + if (readers.find(label) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for map: " << label; + throw IoParameterError(msg.message()); + } + readers.insert( + make_pair(label, new _reader_bits:: + MapReader(map, ir))); + 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 + EdgeMapReader& skipEdgeMap(std::string label, + const ItemReader& ir = ItemReader()) { + if (readers.find(label) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for map: " << label; + throw IoParameterError(msg.message()); + } + readers.insert(make_pair(label, new _reader_bits:: + SkipReader(ir))); + 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 \@mapset, + /// and the header line's name and the mapset's name are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string id; + ls >> command >> id; + return (command == "@edgemaps" || command == "@uedgemaps") && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::vector<_reader_bits::MapReaderBase* > index; + std::string line; + + { + getline(is, line); + std::istringstream ls(line); + std::string id; + while (ls >> id) { + typename MapReaders::iterator it = readers.find(id); + if (it != readers.end()) { + it->second->touch(); + index.push_back(it->second); + } else { + index.push_back(&skipper); + } + } + } + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + if (!it->second->touched()) { + ErrorMessage msg; + msg << "Map not found in file: " << it->first; + throw IoParameterError(msg.message()); + } + } + while (getline(is, line)) { + std::istringstream ls(line); + Edge edge = labelReader->read(ls); + for (int i = 0; i < int(index.size()); ++i) { + index[i]->read(ls, edge); + } + } + } + + virtual void missing() { + if (readers.empty()) return; + ErrorMessage msg; + msg << "EdgeMap section not found in file: @edgemaps " << name; + throw IoParameterError(msg.message()); + } + + private: + + typedef std::map*> MapReaders; + MapReaders readers; + + const Graph& graph; + std::string name; + _reader_bits::SkipReader skipper; + std::auto_ptr<_reader_bits::LabelReaderBase > labelReader; + + }; + + /// \ingroup section_io + /// \brief SectionReader for reading extra undirected edge maps. + /// + /// The lemon format can store maps in the uedgeset sections. This + /// class let you make distinict section to store maps. The main + /// purpose of this class is a logical separation of some maps. The + /// other useful application could be to store paths in undirected + /// edge maps. + /// + /// The first line of the section contains the names of the maps + /// separated with white spaces. Each next line describes an item + /// in the itemset, and contains in the first column the label of + /// the item and then the mapped values for each map. + /// + /// \relates LemonReader + template + class UEdgeMapReader : public LemonReader::SectionReader { + typedef LemonReader::SectionReader Parent; + public: + + typedef _Graph Graph; + typedef typename Graph::Edge Edge; + typedef typename Graph::UEdge UEdge; + typedef _Traits Traits; + typedef typename Traits::Skipper DefaultSkipper; + + /// \brief Constructor. + /// + /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and + /// attach it into the given LemonReader. The reader will read + /// the section when the \c section_name and the \c _name are the same. + template + UEdgeMapReader(LemonReader& _reader, const Graph& _graph, + const _LabelReader& _labelReader, + const std::string& _name = std::string(), + const DefaultSkipper& _skipper = DefaultSkipper()) + : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { + labelReader.reset(new _reader_bits:: + LabelReader(_labelReader)); + } + + + /// \brief Destructor. + /// + /// Destructor for UEdgeMapReader. + virtual ~UEdgeMapReader() { + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + delete it->second; + } + } + + private: + UEdgeMapReader(const UEdgeMapReader&); + void operator=(const UEdgeMapReader&); + + public: + + /// \brief Add a new undirected edge map reader command for the + /// reader. + /// + /// Add a new undirected edge map reader command for the reader. + template + UEdgeMapReader& readUEdgeMap(std::string label, Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, map); + } + + template + UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, map); + } + + /// \brief Add a new undirected edge map reader command for the + /// reader. + /// + /// Add a new undirected edge map reader command for the reader. + template + UEdgeMapReader& readUEdgeMap(std::string label, Map& map, + const ItemReader& ir = ItemReader()) { + return _readMap::Type> + (label, map, ir); + } + + template + UEdgeMapReader& readUEdgeMap(std::string label, const Map& map, + const ItemReader& ir = ItemReader()) { + return _readMap::Type> + (label, map, ir); + } + + private: + + template + UEdgeMapReader& _readMap(std::string label, MapParameter map, + const ItemReader& ir = ItemReader()) { + checkConcept, Map>(); + checkConcept<_reader_bits::ItemReader, ItemReader>(); + if (readers.find(label) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for map: " << label; + throw IoParameterError(msg.message()); + } + readers.insert( + make_pair(label, new _reader_bits:: + MapReader(map, ir))); + 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 + UEdgeMapReader& skipUEdgeMap(std::string label, + const ItemReader& ir = ItemReader()) { + if (readers.find(label) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for map: " << label; + throw IoParameterError(msg.message()); + } + readers.insert(make_pair(label, new _reader_bits:: + SkipReader(ir))); + 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 + UEdgeMapReader& readEdgeMap(std::string label, Map& map) { + return _readDirMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, map); + } + + template + UEdgeMapReader& readEdgeMap(std::string label, const Map& map) { + return _readDirMap< + typename Traits::template Reader, Map, + typename _reader_bits::Arg::Type>(label, 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 + UEdgeMapReader& readEdgeMap(std::string label, Map& map, + const ItemReader& ir = ItemReader()) { + return _readDirMap::Type>(label, map, ir); + } + + template + UEdgeMapReader& readEdgeMap(std::string label, const Map& map, + const ItemReader& ir = ItemReader()) { + return _readDirMap::Type>(label, map, ir); + } + + private: + + template + UEdgeMapReader& _readDirMap(std::string label, MapParameter map, + const ItemReader& ir = ItemReader()) { + checkConcept<_reader_bits::ItemReader, ItemReader>(); + checkConcept, Map>(); + readUEdgeMap("+" + label, + _reader_bits::forwardComposeMap(graph, map), ir); + readUEdgeMap("-" + label, + _reader_bits::backwardComposeMap(graph, map), ir); + 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 + UEdgeMapReader& skipEdgeMap(std::string label, + const ItemReader& ir = ItemReader()) { + skipUEdgeMap("+" + label, ir); + skipUEdgeMap("-" + label, ir); + 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 \@mapset, + /// and the header line's name and the mapset's name are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string id; + ls >> command >> id; + return (command == "@edgemaps" || command == "@uedgemaps") && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::vector<_reader_bits::MapReaderBase* > index; + std::string line; + + { + getline(is, line); + std::istringstream ls(line); + std::string id; + while (ls >> id) { + typename MapReaders::iterator it = readers.find(id); + if (it != readers.end()) { + it->second->touch(); + index.push_back(it->second); + } else { + index.push_back(&skipper); + } + } + } + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + if (!it->second->touched()) { + ErrorMessage msg; + msg << "Map not found in file: " << it->first; + throw IoParameterError(msg.message()); + } + } + while (getline(is, line)) { + std::istringstream ls(line); + UEdge uedge = labelReader->read(ls); + for (int i = 0; i < int(index.size()); ++i) { + index[i]->read(ls, uedge); + } + } + } + + virtual void missing() { + if (readers.empty()) return; + ErrorMessage msg; + msg << "UEdgeMap section not found in file: @uedgemaps " << name; + throw IoParameterError(msg.message()); + } + + private: + + const Graph& graph; + std::string name; + + typedef std::map*> MapReaders; + + MapReaders readers; + _reader_bits::SkipReader skipper; + + std::auto_ptr<_reader_bits::LabelReaderBase > labelReader; + + }; + + /// \ingroup section_io /// \brief SectionReader for retrieve what is in the file. /// /// SectionReader for retrieve what is in the file. If you want diff -r feb7974cf4ec -r 2025a571895e lemon/lemon_writer.h --- a/lemon/lemon_writer.h Tue Aug 28 13:58:54 2007 +0000 +++ b/lemon/lemon_writer.h Tue Aug 28 14:00:42 2007 +0000 @@ -71,6 +71,22 @@ Less less; }; + template + struct UEdgeComposeLess { + UEdgeComposeLess(const UGraph& _ugraph, const Map& _map) + : ugraph(_ugraph), map(_map), less() {} + + bool operator()(const typename UGraph::Edge& p, + const typename UGraph::Edge& q) const { + return p != q ? less(map[p], map[q]) : + (!ugraph.direction(p) && ugraph.direction(q)); + } + + const UGraph& ugraph; + const Map& map; + Less less; + }; + template class ItemLabelWriter { public: @@ -123,8 +139,8 @@ ForwardComposeMap(const Graph& _graph, const Map& _map) : graph(_graph), map(_map) {} - Value operator[](const Key& key) { - return map[graph.direct(key, false)]; + Value operator[](const Key& key) const { + return map[graph.direct(key, true)]; } private: @@ -147,7 +163,7 @@ BackwardComposeMap(const Graph& _graph, const Map& _map) : graph(_graph), map(_map) {} - Value operator[](const Key& key) { + Value operator[](const Key& key) const { return map[graph.direct(key, false)]; } @@ -199,7 +215,7 @@ virtual ~MapWriterBase() {} virtual void write(std::ostream& os, const Item& item) const = 0; - virtual void sortByMap(std::vector&) const = 0; + virtual void sort(std::vector&) const = 0; }; @@ -224,7 +240,59 @@ writer.write(os, value); } - virtual void sortByMap(std::vector& items) const { + virtual void sort(std::vector& items) const { + ComposeLess less(map); + std::sort(items.begin(), items.end(), less); + } + + }; + + template + class UEdgeMapWriterBase { + public: + typedef typename _UGraph::Edge Edge; + typedef typename _UGraph::UEdge UEdge; + + typedef UEdge Item; + + virtual ~UEdgeMapWriterBase() {} + + virtual void write(std::ostream& os, const Item& item) const = 0; + virtual void sort(const _UGraph&, std::vector&) const = 0; + virtual void sort(std::vector&) const = 0; + }; + + + template + class UEdgeMapWriter : public UEdgeMapWriterBase<_UGraph> { + public: + typedef _Map Map; + typedef _Writer Writer; + typedef typename Writer::Value Value; + + typedef typename _UGraph::Edge Edge; + typedef typename _UGraph::UEdge UEdge; + typedef UEdge Item; + + typename _writer_bits::Ref::Type map; + Writer writer; + + UEdgeMapWriter(const Map& _map, const Writer& _writer) + : map(_map), writer(_writer) {} + + virtual ~UEdgeMapWriter() {} + + virtual void write(std::ostream& os, const Item& item) const { + Value value = map[item]; + writer.write(os, value); + } + + virtual void sort(const _UGraph& ugraph, std::vector& items) const { + UEdgeComposeLess<_UGraph, Map> less(ugraph, map); + std::sort(items.begin(), items.end(), less); + } + + virtual void sort(std::vector& items) const { ComposeLess less(map); std::sort(items.begin(), items.end(), less); } @@ -262,7 +330,9 @@ typedef _Item Item; virtual ~LabelWriterBase() {} virtual void write(std::ostream&, const Item&) const = 0; + virtual void sort(std::vector&) const = 0; virtual bool isLabelWriter() const = 0; + virtual LabelWriterBase* clone() const = 0; }; template @@ -279,10 +349,17 @@ virtual void write(std::ostream& os, const Item& item) const { labelWriter.writeLabel(os, item); } + virtual void sort(std::vector& items) const { + labelWriter.sortByLabel(items); + } virtual bool isLabelWriter() const { return labelWriter.isLabelWriter(); } + + virtual LabelWriter* clone() const { + return new LabelWriter(labelWriter); + } }; } @@ -425,7 +502,7 @@ /// \c writeLabel() member will be called with a node it will write it's /// label. Otherwise if the \c _forceLabelMap constructor parameter is true /// then the label map will be the id in the graph. In addition if the - /// the \c _sortByLabel is true then the writer will write the edges + /// the \c _forceSort is true then the writer will write the edges /// sorted by the labels. /// /// \relates LemonWriter @@ -444,13 +521,13 @@ /// attach it into the given LemonWriter. If the \c _forceLabelMap /// parameter is true then the writer will write own label map when /// the user does not give "label" named map. In addition if the - /// the \c _sortByLabel is true then the writer will write the edges + /// the \c _forceSort is true then the writer will write the edges /// sorted by the labels. NodeSetWriter(LemonWriter& _writer, const Graph& _graph, const std::string& _name = std::string(), - bool _forceLabelMap = true, bool _sortByLabel = true) + bool _forceLabelMap = true, bool _forceSort = true) : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), - sortByLabel(_sortByLabel), graph(_graph), name(_name) {} + forceSort(_forceSort), graph(_graph), name(_name) {} /// \brief Destructor. /// @@ -515,9 +592,9 @@ for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { items.push_back(it); } - if (sortByLabel) { + if (forceSort) { if (labelMap) { - labelMap->sortByMap(items); + labelMap->sort(items); } else { typedef IdMap Map; Map map(graph); @@ -550,7 +627,7 @@ /// \brief Returns true if the nodeset can write the labels of the nodes. /// /// Returns true if the nodeset can write the labels of the nodes. - /// It is possible only if an "label" named map was written or the + /// It is possible only if a "label" named map was written or the /// \c _forceLabelMap constructor parameter was true. bool isLabelWriter() const { return labelMap != 0 || forceLabelMap; @@ -558,7 +635,7 @@ /// \brief Write the label of the given node. /// - /// It writes the label of the given node. If there was written an "label" + /// It writes the label of the given node. If there was written a "label" /// named map then it will write the map value belongs to the node. /// Otherwise if the \c forceLabel parameter was true it will write /// its label in the graph. @@ -570,6 +647,23 @@ } } + /// \brief Sorts the given node vector by label. + /// + /// Sorts the given node vector by label. If there was written an + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& nodes) const { + if (labelMap) { + labelMap->sort(nodes); + } else { + typedef IdMap Map; + Map map(graph); + _writer_bits::ComposeLess less(map); + std::sort(nodes.begin(), nodes.end(), less); + } + } + private: typedef std::vector* labelMap; bool forceLabelMap; - bool sortByLabel; + bool forceSort; const Graph& graph; std::string name; @@ -602,7 +696,7 @@ /// \c writeLabel() member will be called with an edge it will write it's /// label. Otherwise if the \c _forceLabelMap constructor parameter is true /// then the label map will be the id in the graph. In addition if the - /// the \c _sortByLabel is true then the writer will write the edges + /// the \c _forceSort is true then the writer will write the edges /// sorted by the labels. /// /// The edgeset writer needs a node label writer to identify which nodes @@ -627,15 +721,15 @@ /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap /// parameter is true then the writer will write own label map if /// the user does not give "label" named map. In addition if the - /// the \c _sortByLabel is true then the writer will write the + /// the \c _forceSort is true then the writer will write the /// edges sorted by the labels. template EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, const NodeLabelWriter& _nodeLabelWriter, const std::string& _name = std::string(), - bool _forceLabelMap = true, bool _sortByLabel = true) + bool _forceLabelMap = true, bool _forceSort = true) : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), - sortByLabel(_sortByLabel), graph(_graph), name(_name) { + forceSort(_forceSort), graph(_graph), name(_name) { checkConcept<_writer_bits::ItemLabelWriter, NodeLabelWriter>(); nodeLabelWriter.reset(new _writer_bits:: LabelWriter(_nodeLabelWriter)); @@ -707,9 +801,9 @@ for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) { items.push_back(it); } - if (sortByLabel) { + if (forceSort) { if (labelMap) { - labelMap->sortByMap(items); + labelMap->sort(items); } else { typedef IdMap Map; Map map(graph); @@ -747,7 +841,7 @@ /// \brief Returns true if the edgeset can write the labels of the edges. /// /// Returns true if the edgeset can write the labels of the edges. - /// It is possible only if an "label" named map was written or the + /// It is possible only if a "label" named map was written or the /// \c _forceLabelMap constructor parameter was true. bool isLabelWriter() const { return forceLabelMap || labelMap != 0; @@ -755,7 +849,7 @@ /// \brief Write the label of the given edge. /// - /// It writes the label of the given edge. If there was written an "label" + /// It writes the label of the given edge. If there was written a "label" /// named map then it will write the map value belongs to the edge. /// Otherwise if the \c forceLabel parameter was true it will write /// its label in the graph. @@ -767,6 +861,23 @@ } } + /// \brief Sorts the given edge vector by label. + /// + /// Sorts the given edge vector by label. If there was written an + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& edges) const { + if (labelMap) { + labelMap->sort(edges); + } else { + typedef IdMap Map; + Map map(graph); + _writer_bits::ComposeLess less(map); + std::sort(edges.begin(), edges.end(), less); + } + } + private: typedef std::vector* labelMap; bool forceLabelMap; - bool sortByLabel; + bool forceSort; const Graph& graph; std::string name; @@ -807,7 +918,7 @@ /// an undirected edge it will write it's label. Otherwise if the \c /// _forceLabelMap constructor parameter is true then the label map /// will be the id in the graph. In addition if the the \c - /// _sortByLabel is true then the writer will write the edges sorted + /// _forceSort is true then the writer will write the edges sorted /// by the labels. /// /// The undirected edgeset writer needs a node label writer to identify @@ -833,18 +944,18 @@ /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap /// parameter is true then the writer will write own label map if /// the user does not give "label" named map. In addition if the - /// the \c _sortByLabel is true then the writer will write the + /// the \c _forceSort is true then the writer will write the /// edges sorted by the labels. template UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, const NodeLabelWriter& _nodeLabelWriter, const std::string& _name = std::string(), - bool _forceLabelMap = true, bool _sortByLabel = true) + bool _forceLabelMap = true, bool _forceSort = true) : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), - sortByLabel(_sortByLabel), graph(_graph), name(_name) { + forceSort(_forceSort), graph(_graph), name(_name) { checkConcept<_writer_bits::ItemLabelWriter, NodeLabelWriter>(); nodeLabelWriter.reset(new _writer_bits:: - LabelWriter(_nodeLabelWriter)); + LabelWriter(_nodeLabelWriter)); } /// \brief Destructor. @@ -882,7 +993,7 @@ checkConcept<_writer_bits::ItemWriter, ItemWriter>(); writers.push_back( make_pair(label, new _writer_bits:: - MapWriter(map, iw))); + UEdgeMapWriter(map, iw))); return *this; } @@ -903,9 +1014,9 @@ const ItemWriter& iw = ItemWriter()) { checkConcept, Map>(); checkConcept<_writer_bits::ItemWriter, ItemWriter>(); - writeUEdgeMap("+" + name, + writeUEdgeMap("+" + label, _writer_bits::forwardComposeMap(graph, map), iw); - writeUEdgeMap("-" + name, + writeUEdgeMap("-" + label, _writer_bits::backwardComposeMap(graph, map), iw); return *this; } @@ -937,9 +1048,9 @@ for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) { items.push_back(it); } - if (sortByLabel) { + if (forceSort) { if (labelMap) { - labelMap->sortByMap(items); + labelMap->sort(items); } else { typedef IdMap Map; Map map(graph); @@ -978,7 +1089,7 @@ /// the edges. /// /// Returns true if the undirected edgeset can write the labels of the - /// undirected edges. It is possible only if an "label" named map was + /// undirected edges. It is possible only if a "label" named map was /// written or the \c _forceLabelMap constructor parameter was true. bool isLabelWriter() const { return forceLabelMap || labelMap != 0; @@ -987,7 +1098,7 @@ /// \brief Write the label of the given undirected edge. /// /// It writes the label of the given undirected edge. If there was written - /// an "label" named map then it will write the map value belongs to the + /// a "label" named map then it will write the map value belongs to the /// undirected edge. Otherwise if the \c forceLabel parameter was true it /// will write its id in the graph. void writeLabel(std::ostream& os, const UEdge& item) const { @@ -1001,32 +1112,66 @@ /// \brief Write the label of the given edge. /// /// It writes the label of the given edge. If there was written - /// an "label" named map then it will write the map value belongs to the + /// a "label" named map then it will write the map value belongs to the /// edge. Otherwise if the \c forceLabel parameter was true it /// will write its id in the graph. If the edge is forward map /// then its prefix character is \c '+' elsewhere \c '-'. void writeLabel(std::ostream& os, const Edge& item) const { if (graph.direction(item)) { - os << "+ "; + os << "+"; } else { - os << "- "; + os << "-"; } if (forceLabelMap) { - os << graph.id(item); + os << graph.id(static_cast(item)); } else { labelMap->write(os, item); } } + /// \brief Sorts the given undirected edge vector by label. + /// + /// Sorts the given undirected edge vector by label. If there was + /// written a "label" named map then the vector will be sorted by + /// the values of this map. Otherwise if the \c forceLabel + /// parameter was true it will be sorted by its id in the graph. + void sortByLabel(std::vector& uedges) const { + if (labelMap) { + labelMap->sort(uedges); + } else { + typedef IdMap Map; + Map map(graph); + _writer_bits::ComposeLess less(map); + std::sort(uedges.begin(), uedges.end(), less); + } + } + + /// \brief Sorts the given edge vector by label. + /// + /// Sorts the given edge vector by label. If there was written a + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& edges) const { + if (labelMap) { + labelMap->sort(graph, edges); + } else { + typedef IdMap Map; + Map map(graph); + _writer_bits::ComposeLess less(map); + std::sort(edges.begin(), edges.end(), less); + } + } + private: typedef std::vector*> > MapWriters; + UEdgeMapWriterBase*> > MapWriters; MapWriters writers; - _writer_bits::MapWriterBase* labelMap; + _writer_bits::UEdgeMapWriterBase* labelMap; bool forceLabelMap; - bool sortByLabel; + bool forceSort; const Graph& graph; std::string name; @@ -1206,6 +1351,7 @@ std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; }; + /// \ingroup section_io /// \brief SectionWriter for writing named undirected edges. /// @@ -1321,6 +1467,429 @@ }; /// \ingroup section_io + /// \brief SectionWriter for writing extra node maps. + /// + /// The lemon format can store maps in the nodeset. This class let + /// you make distinict section to store maps. The main purpose of + /// this class is a logical separation of some maps. The other + /// useful application could be to store paths in node maps. + /// + /// The first line of the section contains the names of the maps + /// separated with white spaces. Each next line describes an item + /// in the itemset, and contains in the first column the label of + /// the item and then the mapped values for each map. + /// + /// \relates LemonWriter + template + class NodeMapWriter : public LemonWriter::SectionWriter { + typedef LemonWriter::SectionWriter Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + + /// \brief Constructor. + /// + /// Constructor for NodeMapWriter. It creates the NodeMapWriter and + /// attach it into the given LemonWriter. If the the + /// \c _forceSort is true then the writer will write the edges + /// sorted by the labels. + template + NodeMapWriter(LemonWriter& _writer, const Graph& _graph, + const _LabelWriter& _labelWriter, + const std::string& _name = std::string(), + bool _forceSort = true) + : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) { + checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); + labelWriter.reset(new _writer_bits::LabelWriter(_labelWriter)); + } + + /// \brief Destructor. + /// + /// Destructor for NodeMapWriter. + virtual ~NodeMapWriter() { + typename MapWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + NodeMapWriter(const NodeMapWriter&); + void operator=(const NodeMapWriter&); + + public: + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + NodeMapWriter& writeNodeMap(std::string label, const Map& map) { + return writeNodeMap, Map>(label, map); + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + NodeMapWriter& writeNodeMap(std::string label, const Map& map, + const ItemWriter& iw = ItemWriter()) { + checkConcept, Map>(); + checkConcept<_writer_bits::ItemWriter,ItemWriter>(); + writers.push_back( + make_pair(label, new _writer_bits:: + MapWriter(map, iw))); + return *this; + } + + protected: + + /// \brief The header of the section. + /// + /// It gives back the header of the section. + virtual std::string header() { + return "@nodemaps " + name; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + std::vector nodes; + for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { + nodes.push_back(it); + } + if (forceSort) { + labelWriter->sort(nodes); + } + os << '\t'; + for (int i = 0; i < int(writers.size()); ++i) { + os << writers[i].first << '\t'; + } + os << std::endl; + for (typename std::vector::iterator it = nodes.begin(); + it != nodes.end(); ++it) { + + labelWriter->write(os, *it); os << '\t'; + for (int i = 0; i < int(writers.size()); ++i) { + writers[i].second->write(os, *it); + os << '\t'; + } + os << std::endl; + } + } + + + private: + + typedef std::vector*> > MapWriters; + MapWriters writers; + + _writer_bits::MapWriterBase* labelMap; + + const Graph& graph; + std::string name; + bool forceSort; + + std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; + }; + + /// \ingroup section_io + /// \brief SectionWriter for writing extra edge maps. + /// + /// The lemon format can store maps in the edgeset. This class let + /// you make distinict section to store maps. The main purpose of + /// this class is a logical separation of some maps. The other + /// useful application could be to store paths in edge maps. + /// + /// The first line of the section contains the names of the maps + /// separated with white spaces. Each next line describes an item + /// in the itemset, and contains in the first column the label of + /// the item and then the mapped values for each map. + /// + /// \relates LemonWriter + template + class EdgeMapWriter : public LemonWriter::SectionWriter { + typedef LemonWriter::SectionWriter Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Edge Edge; + + /// \brief Constructor. + /// + /// Constructor for EdgeMapWriter. It creates the EdgeMapWriter and + /// attach it into the given LemonWriter. If the the + /// \c _forceSort is true then the writer will write the edges + /// sorted by the labels. + template + EdgeMapWriter(LemonWriter& _writer, const Graph& _graph, + const _LabelWriter& _labelWriter, + const std::string& _name = std::string(), + bool _forceSort = true) + : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) { + checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); + labelWriter.reset(new _writer_bits::LabelWriter(_labelWriter)); + } + + /// \brief Destructor. + /// + /// Destructor for EdgeMapWriter. + virtual ~EdgeMapWriter() { + typename MapWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + EdgeMapWriter(const EdgeMapWriter&); + void operator=(const EdgeMapWriter&); + + public: + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + EdgeMapWriter& writeEdgeMap(std::string label, const Map& map) { + return writeEdgeMap, Map>(label, map); + } + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + EdgeMapWriter& writeEdgeMap(std::string label, const Map& map, + const ItemWriter& iw = ItemWriter()) { + checkConcept, Map>(); + checkConcept<_writer_bits::ItemWriter,ItemWriter>(); + writers.push_back( + make_pair(label, new _writer_bits:: + MapWriter(map, iw))); + return *this; + } + + protected: + + /// \brief The header of the section. + /// + /// It gives back the header of the section. + virtual std::string header() { + return "@edgemaps " + name; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + std::vector edges; + for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) { + edges.push_back(it); + } + if (forceSort) { + labelWriter->sort(edges); + } + os << '\t'; + for (int i = 0; i < int(writers.size()); ++i) { + os << writers[i].first << '\t'; + } + os << std::endl; + for (typename std::vector::iterator it = edges.begin(); + it != edges.end(); ++it) { + + labelWriter->write(os, *it); os << '\t'; + for (int i = 0; i < int(writers.size()); ++i) { + writers[i].second->write(os, *it); + os << '\t'; + } + os << std::endl; + } + } + + + private: + + typedef std::vector*> > MapWriters; + MapWriters writers; + + _writer_bits::MapWriterBase* labelMap; + + const Graph& graph; + std::string name; + bool forceSort; + + std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; + }; + + /// \ingroup section_io + /// \brief SectionWriter for writing extra undirected edge maps. + /// + /// The lemon format can store maps in the uedgeset. This class let + /// you make distinict section to store maps. The main purpose of + /// this class is a logical separation of some maps. The other + /// useful application could be to store paths in undirected edge + /// maps. + /// + /// The first line of the section contains the names of the maps + /// separated with white spaces. Each next line describes an item + /// in the itemset, and contains in the first column the label of + /// the item and then the mapped values for each map. + /// + /// \relates LemonWriter + template + class UEdgeMapWriter : public LemonWriter::SectionWriter { + typedef LemonWriter::SectionWriter Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::UEdge UEdge; + typedef typename Graph::Edge Edge; + + /// \brief Constructor. + /// + /// Constructor for UEdgeMapWriter. It creates the UEdgeMapWriter and + /// attach it into the given LemonWriter. If the the + /// \c _forceSort is true then the writer will write the uedges + /// sorted by the labels. + template + UEdgeMapWriter(LemonWriter& _writer, const Graph& _graph, + const _LabelWriter& _labelWriter, + const std::string& _name = std::string(), + bool _forceSort = true) + : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) { + checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); + labelWriter.reset(new _writer_bits::LabelWriter(_labelWriter)); + } + + /// \brief Destructor. + /// + /// Destructor for UEdgeMapWriter. + virtual ~UEdgeMapWriter() { + typename MapWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + UEdgeMapWriter(const UEdgeMapWriter&); + void operator=(const UEdgeMapWriter&); + + public: + + /// \brief Add a new undirected edge map writer command for the writer. + /// + /// Add a new undirected edge map writer command for the writer. + template + UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map) { + return writeUEdgeMap, Map>(label, map); + } + + /// \brief Add a new undirected edge map writer command for the writer. + /// + /// Add a new undirected edge map writer command for the writer. + template + UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map, + const ItemWriter& iw = ItemWriter()) { + checkConcept, Map>(); + checkConcept<_writer_bits::ItemWriter,ItemWriter>(); + writers.push_back( + make_pair(label, new _writer_bits:: + MapWriter(map, iw))); + return *this; + } + + /// \brief Add a new directed edge map writer command for the writer. + /// + /// Add a new directed map writer command for the writer. + template + UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map) { + return writeEdgeMap, Map>(label, map); + } + + /// \brief Add a new directed map writer command for the writer. + /// + /// Add a new directed map writer command for the writer. + template + UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map, + const ItemWriter& iw = ItemWriter()) { + checkConcept, Map>(); + checkConcept<_writer_bits::ItemWriter, ItemWriter>(); + writeUEdgeMap("+" + label, + _writer_bits::forwardComposeMap(graph, map), iw); + writeUEdgeMap("-" + label, + _writer_bits::backwardComposeMap(graph, map), iw); + return *this; + } + + protected: + + /// \brief The header of the section. + /// + /// It gives back the header of the section. + virtual std::string header() { + return "@uedgemaps " + name; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + std::vector uedges; + for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) { + uedges.push_back(it); + } + if (forceSort) { + labelWriter->sort(uedges); + } + os << '\t'; + for (int i = 0; i < int(writers.size()); ++i) { + os << writers[i].first << '\t'; + } + os << std::endl; + for (typename std::vector::iterator it = uedges.begin(); + it != uedges.end(); ++it) { + + labelWriter->write(os, *it); os << '\t'; + for (int i = 0; i < int(writers.size()); ++i) { + writers[i].second->write(os, *it); + os << '\t'; + } + os << std::endl; + } + } + + + private: + + typedef std::vector*> > MapWriters; + MapWriters writers; + + _writer_bits::MapWriterBase* labelMap; + + const Graph& graph; + std::string name; + bool forceSort; + + std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; + }; + + + /// \ingroup section_io /// \brief SectionWriter for attributes. /// /// The lemon format can store multiple attribute set. Each set has diff -r feb7974cf4ec -r 2025a571895e lemon/path_utils.h --- a/lemon/path_utils.h Tue Aug 28 13:58:54 2007 +0000 +++ b/lemon/path_utils.h Tue Aug 28 14:00:42 2007 +0000 @@ -25,6 +25,8 @@ #define LEMON_PATH_UTILS_H #include +#include +#include namespace lemon { @@ -132,6 +134,261 @@ typename Graph::Node pathTarget(const Graph& graph, const Path& path) { return graph.target(path.back()); } + + /// \brief Class which helps to iterate the nodes of a path + /// + /// In a sense, the path can be treated as a list of edges. The + /// lemon path type stores just this list. As a consequence it + /// cannot enumerate the nodes in the path and the zero length paths + /// cannot store the node. + /// + /// This class implements the node iterator of a path structure. To + /// provide this feature, the underlying graph should be given to + /// the constructor of the iterator. + template + class PathNodeIt { + private: + const typename Path::Graph *_graph; + typename Path::EdgeIt _it; + typename Path::Graph::Node _nd; + + public: + + typedef typename Path::Graph Graph; + typedef typename Graph::Node Node; + + /// Default constructor + PathNodeIt() {} + /// Invalid constructor + PathNodeIt(Invalid) + : _graph(0), _it(INVALID), _nd(INVALID) {} + /// Constructor + PathNodeIt(const Graph& graph, const Path& path) + : _graph(&graph), _it(path) { + _nd = (_it != INVALID ? _graph->source(_it) : INVALID); + } + /// Constructor + PathNodeIt(const Graph& graph, const Path& path, const Node& src) + : _graph(&graph), _it(path), _nd(src) {} + + ///Conversion to Graph::Node + operator Node() const { + return _nd; + } + + /// Next node + PathNodeIt& operator++() { + if (_it == INVALID) _nd = INVALID; + else { + _nd = _graph->target(_it); + ++_it; + } + return *this; + } + + /// Comparison operator + bool operator==(const PathNodeIt& n) const { + return _it == n._it && _nd == n._nd; + } + /// Comparison operator + bool operator!=(const PathNodeIt& n) const { + return _it != n._it || _nd != n._nd; + } + /// Comparison operator + bool operator<(const PathNodeIt& n) const { + return (_it < n._it && _nd != INVALID); + } + + }; + + /// \brief Item writer for paths + /// + /// This class can write paths into files. You can store paths in + /// distinict mapset or in attributes section. + /// + ///\code + /// GraphWriter gw(std::cout, g); + /// NodeMapWriter nmw(gw, g, gw); + /// + /// SmartGraph::NodeMap > pnm(g); + /// for (SmartGraph::NodeIt n(g); n != INVALID; ++n) { + /// pnm[n] = bfs.path(n); + /// } + /// nmw.writeNodeMap("pnm", pnm, PathWriter >(gw)); + /// + /// gw.run(); + ///\endcode + /// + /// \warning Do not use this class to write node or edge map values + /// into usual nodesets or edgesets. You will not be able to read + /// back your paths. Rather use NodeMapWriter, EdgeSetWriter or + /// UEdgeSetWriter to dump paths from maps to lemon file. + template + class PathWriter { + private: + + typedef typename Path::Edge Edge; + std::auto_ptr<_writer_bits::LabelWriterBase > edgeLabelWriter; + + public: + + typedef Path Value; + + PathWriter(const PathWriter& pw) { + edgeLabelWriter.reset(pw.edgeLabelWriter->clone()); + } + + /// \brief Constructor + /// + /// The paramter shold be an edge label writer which could + /// be a GraphWriter or an EdgeSetWriter. + template + explicit PathWriter(const EdgeLabelWriter& _edgeLabelWriter) { + edgeLabelWriter.reset(new _writer_bits:: + LabelWriter(_edgeLabelWriter)); + } + + /// \brief Writer function + /// + /// Writes the path to the current stream. The representation + /// is the edge labels beetween parentheses. + void write(std::ostream& os, const Value& value) const { + if (!edgeLabelWriter->isLabelWriter()) { + throw DataFormatError("Cannot find edgeset or label map"); + } + os << '(' << ' '; + for (typename Path::EdgeIt e(value); e != INVALID; ++e) { + edgeLabelWriter->write(os, e); + os << ' '; + } + os << ')'; + } + + }; + + namespace _path_bits { + + template + class PathProxy { + public: + typedef False RevPathTag; + + typedef _Graph Graph; + typedef typename Graph::Edge Edge; + + PathProxy(const std::vector& edges) + : _edges(edges) {} + + int length() const { + return _edges.size(); + } + + bool empty() const { + return _edges.size() == 0; + } + + class EdgeIt { + public: + EdgeIt() {} + EdgeIt(const PathProxy& path) + : _path(&path), _index(0) {} + + operator const Edge() const { + return _path->_edges[_index]; + } + + EdgeIt& operator++() { + ++_index; + return *this; + } + + bool operator==(Invalid) const { + return int(_path->_edges.size()) == _index; + } + bool operator!=(Invalid) const { + return int(_path->_edges.size()) != _index; + } + + private: + const PathProxy* _path; + int _index; + }; + + private: + const std::vector& _edges; + + }; + + } + + /// \brief Item reader for paths + /// + /// This class can read paths from files. You can store paths in + /// distinict mapset or in attributes section. + /// + ///\code + /// GraphReader gr(std::cout, g); + /// NodeMapReader nmr(gr, g, gr); + /// + /// SmartGraph::NodeMap > pnm(g); + /// nmr.readNodeMap("pnm", pnm, PathReader >(gr)); + /// + /// gr.run(); + ///\endcode + /// + /// \warning Do not use this class to read node or edge map values + /// from nodesets or edgesets. The edges are not surely constructed + /// when the edge list should be read. Rather use NodeMapReader, + /// EdgeSetReader or UEdgeSetReader to read distinict map sets from file. + template + class PathReader { + private: + + typedef typename Path::Edge Edge; + std::auto_ptr<_reader_bits::LabelReaderBase > edgeLabelReader; + + public: + + typedef Path Value; + + PathReader(const PathReader& pw) { + edgeLabelReader.reset(pw.edgeLabelReader->clone()); + } + + /// \brief Constructor + /// + /// The paramter shold be an edge label reader which could + /// be a GraphReader or an EdgeSetReader. + template + explicit PathReader(const EdgeLabelReader& _edgeLabelReader) { + edgeLabelReader.reset(new _reader_bits:: + LabelReader(_edgeLabelReader)); + } + + + /// \brief Reader function + /// + /// Reads the path from the current stream. The representation + /// is the edge labels beetween parentheses. + void read(std::istream& is, Value& value) const { + if (!edgeLabelReader->isLabelReader()) { + throw DataFormatError("Cannot find edgeset or label map"); + } + char c; + if (!(is >> c) || c != '(') + throw DataFormatError("PathReader format error"); + std::vector v; + while (is >> c && c != ')') { + is.putback(c); + Edge edge = edgeLabelReader->read(is); + v.push_back(edge); + } + if (!is) throw DataFormatError("PathReader format error"); + copyPath(value, _path_bits::PathProxy(v)); + } + + }; + } #endif