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