1.1 --- a/lemon/lemon_reader.h Sat Oct 20 14:29:12 2007 +0000
1.2 +++ b/lemon/lemon_reader.h Wed Oct 24 16:31:49 2007 +0000
1.3 @@ -311,7 +311,7 @@
1.4
1.5 MapReaderBase() { _touched = false; }
1.6
1.7 - void touch() { _touched = true; }
1.8 + void touch(bool value = true) { _touched = value; }
1.9 bool touched() const { return _touched; }
1.10
1.11 virtual ~MapReaderBase() {}
1.12 @@ -593,8 +593,7 @@
1.13
1.14 virtual int_type underflow() {
1.15 char c;
1.16 - if (_is.read(&c, 1)) {
1.17 - _is.putback(c);
1.18 + if ((c = _is.peek()) != EOF) {
1.19 if (c == '@') {
1.20 return EOF;
1.21 }
1.22 @@ -603,13 +602,13 @@
1.23 }
1.24 char_type *ptr;
1.25 for (ptr = base(); ptr != eptr(); ++ptr) {
1.26 - if (_is.read(&c, 1)) {
1.27 + if ((c = _is.get()) != EOF) {
1.28 if (c == '\n') ++_num;
1.29 if (put_char(c)) {
1.30 *ptr = c;
1.31 } else {
1.32 if (skip_state == after_endl && c == '@') {
1.33 - _is.putback('@');
1.34 + _is.putback(c);
1.35 break;
1.36 }
1.37 --ptr;
1.38 @@ -638,6 +637,36 @@
1.39
1.40 };
1.41
1.42 + static void skipPreSection(std::istream& is, int& line_num) {
1.43 + enum skip_state_type { skip, after_endl };
1.44 +
1.45 + skip_state_type skip_state = after_endl;
1.46 + char c;
1.47 +
1.48 + while ((c = is.get()) != EOF) {
1.49 + if (c == '\n') ++line_num;
1.50 +
1.51 + switch (skip_state) {
1.52 + case skip:
1.53 + if (c == '\n') skip_state = after_endl;
1.54 + break;
1.55 + case after_endl:
1.56 + switch (c) {
1.57 + case '@':
1.58 + is.putback(c);
1.59 + return;
1.60 + case '\n':
1.61 + continue;
1.62 + default:
1.63 + if (!isspace(c)) {
1.64 + skip_state = skip;
1.65 + }
1.66 + break;
1.67 + }
1.68 + }
1.69 + }
1.70 + }
1.71 +
1.72 public:
1.73
1.74 /// \brief Abstract base class for reading a section.
1.75 @@ -722,6 +751,7 @@
1.76 std::string line;
1.77
1.78 SectionReaders::iterator it;
1.79 + skipPreSection(*is, line_num);
1.80 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
1.81 for (it = readers.begin(); it != readers.end(); ++it) {
1.82 if (it->first->header(line)) {
1.83 @@ -732,6 +762,7 @@
1.84 buffer.pubsetbuf(buf, sizeof(buf));
1.85 std::istream ss(&buffer);
1.86 it->first->read(ss);
1.87 + skipPreSection(*is, line_num);
1.88 break;
1.89 } catch (DataFormatError& error) {
1.90 error.line(buffer.line_num());
1.91 @@ -984,6 +1015,465 @@
1.92 };
1.93
1.94 /// \ingroup section_io
1.95 + /// \brief SectionReader for reading a bipartite graph's nodeset.
1.96 + ///
1.97 + /// The lemon format can store multiple bipartite graph nodesets
1.98 + /// with several maps. The bipartite graph nodeset section's header
1.99 + /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
1.100 + /// may be empty.
1.101 + ///
1.102 + /// The first line of the section contains \c "&anodeset" and the
1.103 + /// the names of the A-node maps and regular maps separated with
1.104 + /// white spaces. Each next lines describes an A-node in the anodeset,
1.105 + /// and contains the mapped values for each map. If one of the line
1.106 + /// starts with \c "&bnodeset" then this line contains the names of
1.107 + /// the B-node maps and the regular node maps. And the remaining lines
1.108 + /// contains the mapped values to the B-nodes.
1.109 + ///
1.110 + /// If there is "label" named map then it should be defined in both
1.111 + /// nodeset, and it will be regarded as id map. This map should
1.112 + /// contain only unique values and when the \c readLabel() member
1.113 + /// will read a value from the given stream it will give back that
1.114 + /// node which is mapped to this value.
1.115 + ///
1.116 + /// \relates LemonReader
1.117 + template <typename _Graph, typename _Traits = DefaultReaderTraits>
1.118 + class BpNodeSetReader : public LemonReader::SectionReader {
1.119 + typedef LemonReader::SectionReader Parent;
1.120 + public:
1.121 +
1.122 + typedef _Graph Graph;
1.123 + typedef _Traits Traits;
1.124 + typedef typename Graph::Node Node;
1.125 + typedef typename Traits::Skipper DefaultSkipper;
1.126 +
1.127 + /// \brief Constructor.
1.128 + ///
1.129 + /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
1.130 + /// attach it into the given LemonReader. The nodeset reader will
1.131 + /// add the read nodes to the given Graph. The reader will read
1.132 + /// the section when the \c section_name and the \c _name are the same.
1.133 + BpNodeSetReader(LemonReader& _reader,
1.134 + Graph& _graph,
1.135 + const std::string& _name = std::string(),
1.136 + const DefaultSkipper& _skipper = DefaultSkipper())
1.137 + : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
1.138 +
1.139 +
1.140 + /// \brief Destructor.
1.141 + ///
1.142 + /// Destructor for BpNodeSetReader.
1.143 + virtual ~BpNodeSetReader() {
1.144 + for (typename MapReaders::iterator it = readers.begin();
1.145 + it != readers.end(); ++it) {
1.146 + delete it->second;
1.147 + }
1.148 + }
1.149 +
1.150 + private:
1.151 + BpNodeSetReader(const BpNodeSetReader&);
1.152 + void operator=(const BpNodeSetReader&);
1.153 +
1.154 + public:
1.155 +
1.156 + /// \brief Add a new node map reader command for the reader.
1.157 + ///
1.158 + /// Add a new node map reader command for the reader.
1.159 + template <typename Map>
1.160 + BpNodeSetReader& readNodeMap(std::string label, Map& map) {
1.161 + return _readMap<
1.162 + typename Traits::template Reader<typename Map::Value>, Map,
1.163 + typename _reader_bits::Arg<Map>::Type>(label, map);
1.164 + }
1.165 +
1.166 + template <typename Map>
1.167 + BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
1.168 + return _readMap<
1.169 + typename Traits::template Reader<typename Map::Value>, Map,
1.170 + typename _reader_bits::Arg<Map>::Type>(label, map);
1.171 + }
1.172 +
1.173 + /// \brief Add a new node map reader command for the reader.
1.174 + ///
1.175 + /// Add a new node map reader command for the reader.
1.176 + template <typename ItemReader, typename Map>
1.177 + BpNodeSetReader& readNodeMap(std::string label, Map& map,
1.178 + const ItemReader& ir = ItemReader()) {
1.179 + return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1.180 + (label, map, ir);
1.181 + }
1.182 +
1.183 + template <typename ItemReader, typename Map>
1.184 + BpNodeSetReader& readNodeMap(std::string label, const Map& map,
1.185 + const ItemReader& ir = ItemReader()) {
1.186 + return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1.187 + (label, map, ir);
1.188 + }
1.189 +
1.190 + private:
1.191 +
1.192 + template <typename ItemReader, typename Map, typename MapParameter>
1.193 + BpNodeSetReader& _readMap(std::string label, MapParameter map,
1.194 + const ItemReader& ir = ItemReader()) {
1.195 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1.196 + checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1.197 + if (areaders.find(label) != areaders.end() ||
1.198 + breaders.find(label) != breaders.end() ||
1.199 + readers.find(label) != readers.end()) {
1.200 + ErrorMessage msg;
1.201 + msg << "Multiple read rule for node map: " << label;
1.202 + throw IoParameterError(msg.message());
1.203 + }
1.204 + readers.insert(make_pair(label, new _reader_bits::
1.205 + MapReader<Node, Map, ItemReader>(map, ir)));
1.206 + return *this;
1.207 + }
1.208 +
1.209 + public:
1.210 +
1.211 + /// \brief Add a new A-node map reader command for the reader.
1.212 + ///
1.213 + /// Add a new A-node map reader command for the reader.
1.214 + template <typename Map>
1.215 + BpNodeSetReader& readANodeMap(std::string label, Map& map) {
1.216 + return _readAMap<
1.217 + typename Traits::template Reader<typename Map::Value>, Map,
1.218 + typename _reader_bits::Arg<Map>::Type>(label, map);
1.219 + }
1.220 +
1.221 + template <typename Map>
1.222 + BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
1.223 + return _readAMap<
1.224 + typename Traits::template Reader<typename Map::Value>, Map,
1.225 + typename _reader_bits::Arg<Map>::Type>(label, map);
1.226 + }
1.227 +
1.228 + /// \brief Add a new A-node map reader command for the reader.
1.229 + ///
1.230 + /// Add a new A-node map reader command for the reader.
1.231 + template <typename ItemReader, typename Map>
1.232 + BpNodeSetReader& readANodeMap(std::string label, Map& map,
1.233 + const ItemReader& ir = ItemReader()) {
1.234 + return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1.235 + (label, map, ir);
1.236 + }
1.237 +
1.238 + template <typename ItemReader, typename Map>
1.239 + BpNodeSetReader& readANodeMap(std::string label, const Map& map,
1.240 + const ItemReader& ir = ItemReader()) {
1.241 + return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1.242 + (label, map, ir);
1.243 + }
1.244 +
1.245 + private:
1.246 +
1.247 + template <typename ItemReader, typename Map, typename MapParameter>
1.248 + BpNodeSetReader& _readAMap(std::string label, MapParameter map,
1.249 + const ItemReader& ir = ItemReader()) {
1.250 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1.251 + checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1.252 + if (label == "label") {
1.253 + throw IoParameterError("Label cannot be A-node map");
1.254 + }
1.255 + if (areaders.find(label) != areaders.end() ||
1.256 + readers.find(label) != readers.end()) {
1.257 + ErrorMessage msg;
1.258 + msg << "Multiple read rule for A-node map: " << label;
1.259 + throw IoParameterError(msg.message());
1.260 + }
1.261 + areaders.insert(make_pair(label, new _reader_bits::
1.262 + MapReader<Node, Map, ItemReader>(map, ir)));
1.263 + return *this;
1.264 + }
1.265 +
1.266 + public:
1.267 +
1.268 + /// \brief Add a new B-node map reader command for the reader.
1.269 + ///
1.270 + /// Add a new B-node map reader command for the reader.
1.271 + template <typename Map>
1.272 + BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
1.273 + return _readBMap<
1.274 + typename Traits::template Reader<typename Map::Value>, Map,
1.275 + typename _reader_bits::Arg<Map>::Type>(label, map);
1.276 + }
1.277 +
1.278 + template <typename Map>
1.279 + BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
1.280 + return _readBMap<
1.281 + typename Traits::template Reader<typename Map::Value>, Map,
1.282 + typename _reader_bits::Arg<Map>::Type>(label, map);
1.283 + }
1.284 +
1.285 + /// \brief Add a new B-node map reader command for the reader.
1.286 + ///
1.287 + /// Add a new B-node map reader command for the reader.
1.288 + template <typename ItemReader, typename Map>
1.289 + BpNodeSetReader& readBNodeMap(std::string label, Map& map,
1.290 + const ItemReader& ir = ItemReader()) {
1.291 + return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1.292 + (label, map, ir);
1.293 + }
1.294 +
1.295 + template <typename ItemReader, typename Map>
1.296 + BpNodeSetReader& readBNodeMap(std::string label, const Map& map,
1.297 + const ItemReader& ir = ItemReader()) {
1.298 + return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1.299 + (label, map, ir);
1.300 + }
1.301 +
1.302 + private:
1.303 +
1.304 + template <typename ItemReader, typename Map, typename MapParameter>
1.305 + BpNodeSetReader& _readBMap(std::string label, MapParameter map,
1.306 + const ItemReader& ir = ItemReader()) {
1.307 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1.308 + checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1.309 + if (label == "label") {
1.310 + throw IoParameterError("Label cannot be B-node map");
1.311 + }
1.312 + if (breaders.find(label) != breaders.end() ||
1.313 + readers.find(label) != readers.end()) {
1.314 + ErrorMessage msg;
1.315 + msg << "Multiple read rule for B-node map: " << label;
1.316 + throw IoParameterError(msg.message());
1.317 + }
1.318 + breaders.insert(make_pair(label, new _reader_bits::
1.319 + MapReader<Node, Map, ItemReader>(map, ir)));
1.320 + return *this;
1.321 + }
1.322 +
1.323 + public:
1.324 +
1.325 + /// \brief Add a new node map skipper command for the reader.
1.326 + ///
1.327 + /// Add a new node map skipper command for the reader.
1.328 + template <typename ItemReader>
1.329 + BpNodeSetReader& skipNodeMap(std::string label,
1.330 + const ItemReader& ir = ItemReader()) {
1.331 + if (areaders.find(label) != areaders.end() ||
1.332 + breaders.find(label) != breaders.end() ||
1.333 + readers.find(label) != readers.end()) {
1.334 + ErrorMessage msg;
1.335 + msg << "Multiple read rule for node map: " << label;
1.336 + throw IoParameterError(msg.message());
1.337 + }
1.338 + readers.insert(make_pair(label, new _reader_bits::
1.339 + SkipReader<Node, ItemReader>(ir)));
1.340 + return *this;
1.341 + }
1.342 +
1.343 + /// \brief Add a new A-node map skipper command for the reader.
1.344 + ///
1.345 + /// Add a new A-node map skipper command for the reader.
1.346 + template <typename ItemReader>
1.347 + BpNodeSetReader& skipANodeMap(std::string label,
1.348 + const ItemReader& ir = ItemReader()) {
1.349 + if (label == "label") {
1.350 + throw IoParameterError("Label cannot be A-node map");
1.351 + }
1.352 + if (areaders.find(label) != areaders.end() ||
1.353 + readers.find(label) != readers.end()) {
1.354 + ErrorMessage msg;
1.355 + msg << "Multiple read rule for A-node map: " << label;
1.356 + throw IoParameterError(msg.message());
1.357 + }
1.358 + areaders.insert(make_pair(label, new _reader_bits::
1.359 + SkipReader<Node, ItemReader>(ir)));
1.360 + return *this;
1.361 + }
1.362 +
1.363 + /// \brief Add a new B-node map skipper command for the reader.
1.364 + ///
1.365 + /// Add a new B-node map skipper command for the reader.
1.366 + template <typename ItemReader>
1.367 + BpNodeSetReader& skipBNodeMap(std::string label,
1.368 + const ItemReader& ir = ItemReader()) {
1.369 + if (label == "label") {
1.370 + throw IoParameterError("Label cannot be B-node map");
1.371 + }
1.372 + if (breaders.find(label) != breaders.end() ||
1.373 + readers.find(label) != readers.end()) {
1.374 + ErrorMessage msg;
1.375 + msg << "Multiple read rule for B-node map: " << label;
1.376 + throw IoParameterError(msg.message());
1.377 + }
1.378 + breaders.insert(make_pair(label, new _reader_bits::
1.379 + SkipReader<Node, ItemReader>(ir)));
1.380 + return *this;
1.381 + }
1.382 +
1.383 +
1.384 + protected:
1.385 +
1.386 + /// \brief Gives back true when the SectionReader can process
1.387 + /// the section with the given header line.
1.388 + ///
1.389 + /// It gives back true when the header line starts with \c \@nodeset,
1.390 + /// and the header line's name and the nodeset's name are the same.
1.391 + virtual bool header(const std::string& line) {
1.392 + std::istringstream ls(line);
1.393 + std::string command;
1.394 + std::string id;
1.395 + ls >> command >> id;
1.396 + return command == "@bpnodeset" && name == id;
1.397 + }
1.398 +
1.399 + /// \brief Reader function of the section.
1.400 + ///
1.401 + /// It reads the content of the section.
1.402 + virtual void read(std::istream& is) {
1.403 + std::string line;
1.404 + {
1.405 + std::vector<_reader_bits::MapReaderBase<Node>* > index;
1.406 + {
1.407 + getline(is, line);
1.408 + std::istringstream ls(line);
1.409 + std::string id;
1.410 + ls >> id;
1.411 + if (id != "&anodeset") {
1.412 + throw IoParameterError("Cannot find &anodeset subsection");
1.413 + }
1.414 + while (ls >> id) {
1.415 + typename MapReaders::iterator it = readers.find(id);
1.416 + typename MapReaders::iterator ait = areaders.find(id);
1.417 + if (it != readers.end()) {
1.418 + it->second->touch();
1.419 + index.push_back(it->second);
1.420 + } else if (ait != areaders.end()) {
1.421 + ait->second->touch();
1.422 + index.push_back(ait->second);
1.423 + }
1.424 + if (id == "label") {
1.425 + inverter.reset(index.back()->getInverter());
1.426 + index.back() = inverter.get();
1.427 + }
1.428 + }
1.429 + }
1.430 + for (typename MapReaders::iterator it = areaders.begin();
1.431 + it != areaders.end(); ++it) {
1.432 + if (!it->second->touched()) {
1.433 + ErrorMessage msg;
1.434 + msg << "Map not found in file: " << it->first;
1.435 + throw IoParameterError(msg.message());
1.436 + }
1.437 + }
1.438 + for (typename MapReaders::iterator it = readers.begin();
1.439 + it != readers.end(); ++it) {
1.440 + if (!it->second->touched()) {
1.441 + ErrorMessage msg;
1.442 + msg << "Map not found in file: " << it->first;
1.443 + throw IoParameterError(msg.message());
1.444 + }
1.445 + it->second->touch(false);
1.446 + }
1.447 +
1.448 + while (getline(is, line)) {
1.449 + if (line[0] == '&') {
1.450 + std::istringstream ls(line);
1.451 + std::string id;
1.452 + ls >> id;
1.453 + if (id == "&bnodeset") break;
1.454 + }
1.455 + Node node = graph.addANode();
1.456 + std::istringstream ls(line);
1.457 + for (int i = 0; i < int(index.size()); ++i) {
1.458 + index[i]->read(ls, node);
1.459 + }
1.460 + }
1.461 + }
1.462 +
1.463 + {
1.464 + std::vector<_reader_bits::MapReaderBase<Node>* > index;
1.465 + {
1.466 + std::istringstream ls(line);
1.467 + std::string id;
1.468 + ls >> id;
1.469 + if (id != "&bnodeset") {
1.470 + throw IoParameterError("Cannot find &bnodeset subsection");
1.471 + }
1.472 + while (ls >> id) {
1.473 + typename MapReaders::iterator it = readers.find(id);
1.474 + typename MapReaders::iterator bit = breaders.find(id);
1.475 + if (it != readers.end()) {
1.476 + it->second->touch();
1.477 + index.push_back(it->second);
1.478 + } else if (bit != breaders.end()) {
1.479 + bit->second->touch();
1.480 + index.push_back(bit->second);
1.481 + }
1.482 + if (id == "label" && inverter.get() != 0) {
1.483 + index.back() = inverter.get();
1.484 + }
1.485 + }
1.486 + }
1.487 + for (typename MapReaders::iterator it = breaders.begin();
1.488 + it != breaders.end(); ++it) {
1.489 + if (!it->second->touched()) {
1.490 + ErrorMessage msg;
1.491 + msg << "Map not found in file: " << it->first;
1.492 + throw IoParameterError(msg.message());
1.493 + }
1.494 + }
1.495 + for (typename MapReaders::iterator it = readers.begin();
1.496 + it != readers.end(); ++it) {
1.497 + if (!it->second->touched()) {
1.498 + ErrorMessage msg;
1.499 + msg << "Map not found in file: " << it->first;
1.500 + throw IoParameterError(msg.message());
1.501 + }
1.502 + }
1.503 + while (getline(is, line)) {
1.504 + Node node = graph.addBNode();
1.505 + std::istringstream ls(line);
1.506 + for (int i = 0; i < int(index.size()); ++i) {
1.507 + index[i]->read(ls, node);
1.508 + }
1.509 + }
1.510 + }
1.511 + }
1.512 +
1.513 + virtual void missing() {
1.514 + if (readers.empty()) return;
1.515 + ErrorMessage msg;
1.516 + msg << "BpNodeSet section not found in file: @bpnodeset " << name;
1.517 + throw IoParameterError(msg.message());
1.518 + }
1.519 +
1.520 + public:
1.521 +
1.522 + /// \brief Returns true if the nodeset can give back the node by its label.
1.523 + ///
1.524 + /// Returns true if the nodeset can give back the node by its label.
1.525 + /// It is possible only if an "label" named map was read.
1.526 + bool isLabelReader() const {
1.527 + return inverter.get() != 0;
1.528 + }
1.529 +
1.530 + /// \brief Gives back the node by its label.
1.531 + ///
1.532 + /// It reads an id from the stream and gives back which node belongs to
1.533 + /// it. It is possible only if there was read an "label" named map.
1.534 + void readLabel(std::istream& is, Node& node) const {
1.535 + node = inverter->read(is);
1.536 + }
1.537 +
1.538 + private:
1.539 +
1.540 + typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*>
1.541 + MapReaders;
1.542 +
1.543 + MapReaders areaders, breaders, readers;
1.544 +
1.545 + Graph& graph;
1.546 + std::string name;
1.547 + _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
1.548 +
1.549 + std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
1.550 + };
1.551 +
1.552 +
1.553 + /// \ingroup section_io
1.554 /// \brief SectionReader for reading a graph's edgeset.
1.555 ///
1.556 /// The lemon format can store multiple graph edgesets with several maps.