lemon/lemon_reader.h
changeset 2503 15b3bf0141c7
parent 2476 059dcdda37c5
child 2504 46a82ce84cc6
equal deleted inserted replaced
37:e6d931a48953 38:ead93491a6b7
   309     public:
   309     public:
   310       typedef _Item Item;
   310       typedef _Item Item;
   311 
   311 
   312       MapReaderBase() { _touched = false; }
   312       MapReaderBase() { _touched = false; }
   313       
   313       
   314       void touch() { _touched = true; }
   314       void touch(bool value = true) { _touched = value; }
   315       bool touched() const { return _touched; }
   315       bool touched() const { return _touched; }
   316 
   316 
   317       virtual ~MapReaderBase() {}
   317       virtual ~MapReaderBase() {}
   318 
   318 
   319       virtual void read(std::istream& is, const Item& item) = 0;
   319       virtual void read(std::istream& is, const Item& item) = 0;
   591 	return false;
   591 	return false;
   592       }
   592       }
   593 
   593 
   594       virtual int_type underflow() {
   594       virtual int_type underflow() {
   595 	char c;
   595 	char c;
   596 	if (_is.read(&c, 1)) {
   596 	if ((c = _is.peek()) != EOF) {
   597 	  _is.putback(c);
       
   598 	  if (c == '@') {
   597 	  if (c == '@') {
   599 	    return EOF;
   598 	    return EOF;
   600 	  }
   599 	  }
   601 	} else {
   600 	} else {
   602 	  return EOF;
   601 	  return EOF;
   603 	}
   602 	}
   604 	char_type *ptr;
   603 	char_type *ptr;
   605 	for (ptr = base(); ptr != eptr(); ++ptr) {
   604 	for (ptr = base(); ptr != eptr(); ++ptr) {
   606 	  if (_is.read(&c, 1)) {
   605 	  if ((c = _is.get()) != EOF) {
   607 	    if (c == '\n') ++_num;
   606 	    if (c == '\n') ++_num;
   608 	    if (put_char(c)) {
   607 	    if (put_char(c)) {
   609 	      *ptr = c;
   608 	      *ptr = c;
   610 	    } else {
   609 	    } else {
   611 	      if (skip_state == after_endl && c == '@') {
   610 	      if (skip_state == after_endl && c == '@') {
   612 		_is.putback('@');
   611 		_is.putback(c);
   613 		break;
   612 		break;
   614 	      }
   613 	      }
   615 	      --ptr;
   614 	      --ptr;
   616 	    }
   615 	    }
   617 	  } else {
   616 	  } else {
   635 	}
   634 	}
   636 	return r;
   635 	return r;
   637       }
   636       }
   638 
   637 
   639     };
   638     };
       
   639 
       
   640     static void skipPreSection(std::istream& is, int& line_num) {
       
   641       enum skip_state_type { skip, after_endl };
       
   642 
       
   643       skip_state_type skip_state = after_endl;
       
   644       char c;
       
   645       
       
   646       while ((c = is.get()) != EOF) {
       
   647 	if (c == '\n') ++line_num;
       
   648 
       
   649 	switch (skip_state) {
       
   650 	case skip:
       
   651 	  if (c == '\n') skip_state = after_endl;
       
   652 	  break;
       
   653 	case after_endl:
       
   654 	  switch (c) {
       
   655 	  case '@':
       
   656 	    is.putback(c);
       
   657 	    return;
       
   658 	  case '\n':
       
   659 	    continue;
       
   660 	  default:
       
   661 	    if (!isspace(c)) {
       
   662 	      skip_state = skip;
       
   663 	    }
       
   664 	    break;
       
   665 	  }
       
   666 	}	
       
   667       }
       
   668     }
   640 
   669 
   641   public:
   670   public:
   642 
   671 
   643     /// \brief Abstract base class for reading a section.
   672     /// \brief Abstract base class for reading a section.
   644     ///
   673     ///
   720     void run() {
   749     void run() {
   721       int line_num = 0;
   750       int line_num = 0;
   722       std::string line;
   751       std::string line;
   723       
   752       
   724       SectionReaders::iterator it;
   753       SectionReaders::iterator it;
       
   754       skipPreSection(*is, line_num);
   725       while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   755       while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   726 	for (it = readers.begin(); it != readers.end(); ++it) {
   756 	for (it = readers.begin(); it != readers.end(); ++it) {
   727 	  if (it->first->header(line)) {
   757 	  if (it->first->header(line)) {
   728 	    it->second = true;
   758 	    it->second = true;
   729 	    char buf[2048];
   759 	    char buf[2048];
   730 	    FilterStreamBuf buffer(*is, line_num);
   760 	    FilterStreamBuf buffer(*is, line_num);
   731 	    try {
   761 	    try {
   732 	      buffer.pubsetbuf(buf, sizeof(buf));
   762 	      buffer.pubsetbuf(buf, sizeof(buf));
   733 	      std::istream ss(&buffer);
   763 	      std::istream ss(&buffer);
   734 	      it->first->read(ss);
   764 	      it->first->read(ss);
       
   765 	      skipPreSection(*is, line_num);
   735 	      break;
   766 	      break;
   736 	    } catch (DataFormatError& error) {
   767 	    } catch (DataFormatError& error) {
   737 	      error.line(buffer.line_num());
   768 	      error.line(buffer.line_num());
   738 	      throw;
   769 	      throw;
   739 	    }	
   770 	    }	
   980     std::string name;
  1011     std::string name;
   981     _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
  1012     _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
   982 
  1013 
   983     std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
  1014     std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
   984   };
  1015   };
       
  1016 
       
  1017   /// \ingroup section_io
       
  1018   /// \brief SectionReader for reading a bipartite graph's nodeset.
       
  1019   ///
       
  1020   /// The lemon format can store multiple bipartite graph nodesets
       
  1021   /// with several maps. The bipartite graph nodeset section's header
       
  1022   /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
       
  1023   /// may be empty.
       
  1024   ///
       
  1025   /// The first line of the section contains \c "&anodeset" and the
       
  1026   /// the names of the A-node maps and regular maps separated with
       
  1027   /// white spaces. Each next lines describes an A-node in the anodeset,
       
  1028   /// and contains the mapped values for each map. If one of the line
       
  1029   /// starts with \c "&bnodeset" then this line contains the names of
       
  1030   /// the B-node maps and the regular node maps. And the remaining lines
       
  1031   /// contains the mapped values to the B-nodes.
       
  1032   ///
       
  1033   /// If there is "label" named map then it should be defined in both
       
  1034   /// nodeset, and it will be regarded as id map. This map should
       
  1035   /// contain only unique values and when the \c readLabel() member
       
  1036   /// will read a value from the given stream it will give back that
       
  1037   /// node which is mapped to this value.
       
  1038   ///
       
  1039   /// \relates LemonReader
       
  1040   template <typename _Graph, typename _Traits = DefaultReaderTraits>
       
  1041   class BpNodeSetReader : public LemonReader::SectionReader {
       
  1042     typedef LemonReader::SectionReader Parent;
       
  1043   public:
       
  1044 
       
  1045     typedef _Graph Graph;
       
  1046     typedef _Traits Traits;
       
  1047     typedef typename Graph::Node Node;
       
  1048     typedef typename Traits::Skipper DefaultSkipper;
       
  1049 
       
  1050     /// \brief Constructor.
       
  1051     ///
       
  1052     /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
       
  1053     /// attach it into the given LemonReader. The nodeset reader will
       
  1054     /// add the read nodes to the given Graph. The reader will read
       
  1055     /// the section when the \c section_name and the \c _name are the same. 
       
  1056     BpNodeSetReader(LemonReader& _reader, 
       
  1057 		  Graph& _graph, 
       
  1058 		  const std::string& _name = std::string(),
       
  1059 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
       
  1060       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
       
  1061 
       
  1062 
       
  1063     /// \brief Destructor.
       
  1064     ///
       
  1065     /// Destructor for BpNodeSetReader.
       
  1066     virtual ~BpNodeSetReader() {
       
  1067       for (typename MapReaders::iterator it = readers.begin(); 
       
  1068 	   it != readers.end(); ++it) {
       
  1069 	delete it->second;
       
  1070       }
       
  1071     }
       
  1072 
       
  1073   private:
       
  1074     BpNodeSetReader(const BpNodeSetReader&);
       
  1075     void operator=(const BpNodeSetReader&);
       
  1076   
       
  1077   public:
       
  1078 
       
  1079     /// \brief Add a new node map reader command for the reader.
       
  1080     ///
       
  1081     /// Add a new node map reader command for the reader.
       
  1082     template <typename Map>
       
  1083     BpNodeSetReader& readNodeMap(std::string label, Map& map) {
       
  1084       return _readMap<
       
  1085 	typename Traits::template Reader<typename Map::Value>, Map,
       
  1086 	typename _reader_bits::Arg<Map>::Type>(label, map);
       
  1087     }
       
  1088 
       
  1089     template <typename Map>
       
  1090     BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
       
  1091       return _readMap<
       
  1092 	typename Traits::template Reader<typename Map::Value>, Map,
       
  1093 	typename _reader_bits::Arg<Map>::Type>(label, map);
       
  1094     }
       
  1095 
       
  1096     /// \brief Add a new node map reader command for the reader.
       
  1097     ///
       
  1098     /// Add a new node map reader command for the reader.
       
  1099     template <typename ItemReader, typename Map>
       
  1100     BpNodeSetReader& readNodeMap(std::string label, Map& map, 
       
  1101 			       const ItemReader& ir = ItemReader()) {
       
  1102       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
       
  1103 	(label, map, ir);
       
  1104     }
       
  1105 
       
  1106     template <typename ItemReader, typename Map>
       
  1107     BpNodeSetReader& readNodeMap(std::string label, const Map& map, 
       
  1108 			       const ItemReader& ir = ItemReader()) {
       
  1109       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
       
  1110 	(label, map, ir);
       
  1111     }
       
  1112 
       
  1113   private:
       
  1114 
       
  1115     template <typename ItemReader, typename Map, typename MapParameter>
       
  1116     BpNodeSetReader& _readMap(std::string label, MapParameter map, 
       
  1117 			    const ItemReader& ir = ItemReader()) {
       
  1118       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
       
  1119       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
       
  1120       if (areaders.find(label) != areaders.end() ||
       
  1121 	  breaders.find(label) != breaders.end() ||
       
  1122 	  readers.find(label) != readers.end()) {
       
  1123 	ErrorMessage msg;
       
  1124 	msg << "Multiple read rule for node map: " << label;
       
  1125 	throw IoParameterError(msg.message());
       
  1126       }      
       
  1127       readers.insert(make_pair(label, new _reader_bits::
       
  1128 		  MapReader<Node, Map, ItemReader>(map, ir)));
       
  1129       return *this;
       
  1130     }
       
  1131 
       
  1132   public:
       
  1133 
       
  1134     /// \brief Add a new A-node map reader command for the reader.
       
  1135     ///
       
  1136     /// Add a new A-node map reader command for the reader.
       
  1137     template <typename Map>
       
  1138     BpNodeSetReader& readANodeMap(std::string label, Map& map) {
       
  1139       return _readAMap<
       
  1140 	typename Traits::template Reader<typename Map::Value>, Map,
       
  1141 	typename _reader_bits::Arg<Map>::Type>(label, map);
       
  1142     }
       
  1143 
       
  1144     template <typename Map>
       
  1145     BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
       
  1146       return _readAMap<
       
  1147 	typename Traits::template Reader<typename Map::Value>, Map,
       
  1148 	typename _reader_bits::Arg<Map>::Type>(label, map);
       
  1149     }
       
  1150 
       
  1151     /// \brief Add a new A-node map reader command for the reader.
       
  1152     ///
       
  1153     /// Add a new A-node map reader command for the reader.
       
  1154     template <typename ItemReader, typename Map>
       
  1155     BpNodeSetReader& readANodeMap(std::string label, Map& map, 
       
  1156 			       const ItemReader& ir = ItemReader()) {
       
  1157       return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
       
  1158 	(label, map, ir);
       
  1159     }
       
  1160 
       
  1161     template <typename ItemReader, typename Map>
       
  1162     BpNodeSetReader& readANodeMap(std::string label, const Map& map, 
       
  1163 			       const ItemReader& ir = ItemReader()) {
       
  1164       return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
       
  1165 	(label, map, ir);
       
  1166     }
       
  1167 
       
  1168   private:
       
  1169 
       
  1170     template <typename ItemReader, typename Map, typename MapParameter>
       
  1171     BpNodeSetReader& _readAMap(std::string label, MapParameter map, 
       
  1172 			    const ItemReader& ir = ItemReader()) {
       
  1173       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
       
  1174       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
       
  1175       if (label == "label") {
       
  1176 	throw IoParameterError("Label cannot be A-node map");
       
  1177       }
       
  1178       if (areaders.find(label) != areaders.end() ||
       
  1179 	  readers.find(label) != readers.end()) {
       
  1180 	ErrorMessage msg;
       
  1181 	msg << "Multiple read rule for A-node map: " << label;
       
  1182 	throw IoParameterError(msg.message());
       
  1183       }
       
  1184       areaders.insert(make_pair(label, new _reader_bits::
       
  1185 				MapReader<Node, Map, ItemReader>(map, ir)));
       
  1186       return *this;
       
  1187     }
       
  1188 
       
  1189   public:
       
  1190 
       
  1191     /// \brief Add a new B-node map reader command for the reader.
       
  1192     ///
       
  1193     /// Add a new B-node map reader command for the reader.
       
  1194     template <typename Map>
       
  1195     BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
       
  1196       return _readBMap<
       
  1197 	typename Traits::template Reader<typename Map::Value>, Map,
       
  1198 	typename _reader_bits::Arg<Map>::Type>(label, map);
       
  1199     }
       
  1200 
       
  1201     template <typename Map>
       
  1202     BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
       
  1203       return _readBMap<
       
  1204 	typename Traits::template Reader<typename Map::Value>, Map,
       
  1205 	typename _reader_bits::Arg<Map>::Type>(label, map);
       
  1206     }
       
  1207 
       
  1208     /// \brief Add a new B-node map reader command for the reader.
       
  1209     ///
       
  1210     /// Add a new B-node map reader command for the reader.
       
  1211     template <typename ItemReader, typename Map>
       
  1212     BpNodeSetReader& readBNodeMap(std::string label, Map& map, 
       
  1213 			       const ItemReader& ir = ItemReader()) {
       
  1214       return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
       
  1215 	(label, map, ir);
       
  1216     }
       
  1217 
       
  1218     template <typename ItemReader, typename Map>
       
  1219     BpNodeSetReader& readBNodeMap(std::string label, const Map& map, 
       
  1220 			       const ItemReader& ir = ItemReader()) {
       
  1221       return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
       
  1222 	(label, map, ir);
       
  1223     }
       
  1224 
       
  1225   private:
       
  1226 
       
  1227     template <typename ItemReader, typename Map, typename MapParameter>
       
  1228     BpNodeSetReader& _readBMap(std::string label, MapParameter map, 
       
  1229 			    const ItemReader& ir = ItemReader()) {
       
  1230       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
       
  1231       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
       
  1232       if (label == "label") {
       
  1233 	throw IoParameterError("Label cannot be B-node map");
       
  1234       }
       
  1235       if (breaders.find(label) != breaders.end() ||
       
  1236 	  readers.find(label) != readers.end()) {
       
  1237 	ErrorMessage msg;
       
  1238 	msg << "Multiple read rule for B-node map: " << label;
       
  1239 	throw IoParameterError(msg.message());
       
  1240       }
       
  1241       breaders.insert(make_pair(label, new _reader_bits::
       
  1242 				MapReader<Node, Map, ItemReader>(map, ir)));
       
  1243       return *this;
       
  1244     }
       
  1245 
       
  1246   public:
       
  1247 
       
  1248     /// \brief Add a new node map skipper command for the reader.
       
  1249     ///
       
  1250     /// Add a new node map skipper command for the reader.
       
  1251     template <typename ItemReader>
       
  1252     BpNodeSetReader& skipNodeMap(std::string label, 
       
  1253 				 const ItemReader& ir = ItemReader()) {
       
  1254       if (areaders.find(label) != areaders.end() ||
       
  1255 	  breaders.find(label) != breaders.end() ||
       
  1256 	  readers.find(label) != readers.end()) {
       
  1257 	ErrorMessage msg;
       
  1258 	msg << "Multiple read rule for node map: " << label;
       
  1259 	throw IoParameterError(msg.message());
       
  1260       }
       
  1261       readers.insert(make_pair(label, new _reader_bits::
       
  1262 			       SkipReader<Node, ItemReader>(ir)));
       
  1263       return *this;
       
  1264     }
       
  1265 
       
  1266     /// \brief Add a new A-node map skipper command for the reader.
       
  1267     ///
       
  1268     /// Add a new A-node map skipper command for the reader.
       
  1269     template <typename ItemReader>
       
  1270     BpNodeSetReader& skipANodeMap(std::string label, 
       
  1271 				  const ItemReader& ir = ItemReader()) {
       
  1272       if (label == "label") {
       
  1273 	throw IoParameterError("Label cannot be A-node map");
       
  1274       }
       
  1275       if (areaders.find(label) != areaders.end() ||
       
  1276 	  readers.find(label) != readers.end()) {
       
  1277 	ErrorMessage msg;
       
  1278 	msg << "Multiple read rule for A-node map: " << label;
       
  1279 	throw IoParameterError(msg.message());
       
  1280       }
       
  1281       areaders.insert(make_pair(label, new _reader_bits::
       
  1282 				SkipReader<Node, ItemReader>(ir)));
       
  1283       return *this;
       
  1284     }
       
  1285 
       
  1286     /// \brief Add a new B-node map skipper command for the reader.
       
  1287     ///
       
  1288     /// Add a new B-node map skipper command for the reader.
       
  1289     template <typename ItemReader>
       
  1290     BpNodeSetReader& skipBNodeMap(std::string label, 
       
  1291 				  const ItemReader& ir = ItemReader()) {
       
  1292       if (label == "label") {
       
  1293 	throw IoParameterError("Label cannot be B-node map");
       
  1294       }
       
  1295       if (breaders.find(label) != breaders.end() ||
       
  1296 	  readers.find(label) != readers.end()) {
       
  1297 	ErrorMessage msg;
       
  1298 	msg << "Multiple read rule for B-node map: " << label;
       
  1299 	throw IoParameterError(msg.message());
       
  1300       }
       
  1301       breaders.insert(make_pair(label, new _reader_bits::
       
  1302 				SkipReader<Node, ItemReader>(ir)));
       
  1303       return *this;
       
  1304     }
       
  1305 
       
  1306 
       
  1307   protected:
       
  1308 
       
  1309     /// \brief Gives back true when the SectionReader can process 
       
  1310     /// the section with the given header line.
       
  1311     ///
       
  1312     /// It gives back true when the header line starts with \c \@nodeset,
       
  1313     /// and the header line's name and the nodeset's name are the same.
       
  1314     virtual bool header(const std::string& line) {
       
  1315       std::istringstream ls(line);
       
  1316       std::string command;
       
  1317       std::string id;
       
  1318       ls >> command >> id;
       
  1319       return command == "@bpnodeset" && name == id;
       
  1320     }
       
  1321 
       
  1322     /// \brief Reader function of the section.
       
  1323     ///
       
  1324     /// It reads the content of the section.
       
  1325     virtual void read(std::istream& is) {
       
  1326       std::string line;
       
  1327       {
       
  1328 	std::vector<_reader_bits::MapReaderBase<Node>* > index;
       
  1329 	{
       
  1330 	  getline(is, line);
       
  1331 	  std::istringstream ls(line);
       
  1332 	  std::string id;
       
  1333 	  ls >> id;
       
  1334 	  if (id != "&anodeset") {
       
  1335 	    throw IoParameterError("Cannot find &anodeset subsection");
       
  1336 	  }
       
  1337 	  while (ls >> id) {
       
  1338 	    typename MapReaders::iterator it = readers.find(id);
       
  1339 	    typename MapReaders::iterator ait = areaders.find(id);
       
  1340 	    if (it != readers.end()) {
       
  1341 	      it->second->touch();
       
  1342 	      index.push_back(it->second);
       
  1343 	    } else if (ait != areaders.end()) {
       
  1344 	      ait->second->touch();
       
  1345 	      index.push_back(ait->second);
       
  1346 	    }
       
  1347 	    if (id == "label") {
       
  1348 	      inverter.reset(index.back()->getInverter());
       
  1349 	      index.back() = inverter.get();
       
  1350 	    }
       
  1351 	  }
       
  1352 	}
       
  1353 	for (typename MapReaders::iterator it = areaders.begin();
       
  1354 	     it != areaders.end(); ++it) {
       
  1355 	  if (!it->second->touched()) {
       
  1356 	    ErrorMessage msg;
       
  1357 	    msg << "Map not found in file: " << it->first;
       
  1358 	    throw IoParameterError(msg.message());
       
  1359 	  }
       
  1360 	}
       
  1361 	for (typename MapReaders::iterator it = readers.begin();
       
  1362 	     it != readers.end(); ++it) {
       
  1363 	  if (!it->second->touched()) {
       
  1364 	    ErrorMessage msg;
       
  1365 	    msg << "Map not found in file: " << it->first;
       
  1366 	    throw IoParameterError(msg.message());
       
  1367 	  }
       
  1368 	  it->second->touch(false);
       
  1369 	}
       
  1370 
       
  1371 	while (getline(is, line)) {
       
  1372 	  if (line[0] == '&') {
       
  1373 	    std::istringstream ls(line);
       
  1374 	    std::string id;
       
  1375 	    ls >> id;
       
  1376 	    if (id == "&bnodeset") break;
       
  1377 	  }
       
  1378 	  Node node = graph.addANode();
       
  1379 	  std::istringstream ls(line);
       
  1380 	  for (int i = 0; i < int(index.size()); ++i) {
       
  1381 	    index[i]->read(ls, node);
       
  1382 	  }
       
  1383 	}
       
  1384       }
       
  1385 
       
  1386       {
       
  1387 	std::vector<_reader_bits::MapReaderBase<Node>* > index;
       
  1388 	{
       
  1389 	  std::istringstream ls(line);
       
  1390 	  std::string id;
       
  1391 	  ls >> id;
       
  1392 	  if (id != "&bnodeset") {
       
  1393 	    throw IoParameterError("Cannot find &bnodeset subsection");
       
  1394 	  }
       
  1395 	  while (ls >> id) {
       
  1396 	    typename MapReaders::iterator it = readers.find(id);
       
  1397 	    typename MapReaders::iterator bit = breaders.find(id);
       
  1398 	    if (it != readers.end()) {
       
  1399 	      it->second->touch();
       
  1400 	      index.push_back(it->second);
       
  1401 	    } else if (bit != breaders.end()) {
       
  1402 	      bit->second->touch();
       
  1403 	      index.push_back(bit->second);
       
  1404 	    }
       
  1405 	    if (id == "label" && inverter.get() != 0) {
       
  1406 	      index.back() = inverter.get();
       
  1407 	    }
       
  1408 	  }
       
  1409 	}
       
  1410 	for (typename MapReaders::iterator it = breaders.begin();
       
  1411 	     it != breaders.end(); ++it) {
       
  1412 	  if (!it->second->touched()) {
       
  1413 	    ErrorMessage msg;
       
  1414 	    msg << "Map not found in file: " << it->first;
       
  1415 	    throw IoParameterError(msg.message());
       
  1416 	  }
       
  1417 	}
       
  1418 	for (typename MapReaders::iterator it = readers.begin();
       
  1419 	     it != readers.end(); ++it) {
       
  1420 	  if (!it->second->touched()) {
       
  1421 	    ErrorMessage msg;
       
  1422 	    msg << "Map not found in file: " << it->first;
       
  1423 	    throw IoParameterError(msg.message());
       
  1424 	  }
       
  1425 	}
       
  1426 	while (getline(is, line)) {	
       
  1427 	  Node node = graph.addBNode();
       
  1428 	  std::istringstream ls(line);
       
  1429 	  for (int i = 0; i < int(index.size()); ++i) {
       
  1430 	    index[i]->read(ls, node);
       
  1431 	  }
       
  1432 	}
       
  1433       }
       
  1434     }
       
  1435 
       
  1436     virtual void missing() {
       
  1437       if (readers.empty()) return;
       
  1438       ErrorMessage msg;
       
  1439       msg << "BpNodeSet section not found in file: @bpnodeset " << name;
       
  1440       throw IoParameterError(msg.message());
       
  1441     }
       
  1442 
       
  1443   public:
       
  1444 
       
  1445     /// \brief Returns true if the nodeset can give back the node by its label.
       
  1446     ///
       
  1447     /// Returns true if the nodeset can give back the node by its label.
       
  1448     /// It is possible only if an "label" named map was read.
       
  1449     bool isLabelReader() const {
       
  1450       return inverter.get() != 0;
       
  1451     }
       
  1452 
       
  1453     /// \brief Gives back the node by its label.
       
  1454     ///
       
  1455     /// It reads an id from the stream and gives back which node belongs to
       
  1456     /// it. It is possible only if there was read an "label" named map.
       
  1457     void readLabel(std::istream& is, Node& node) const {
       
  1458       node = inverter->read(is);
       
  1459     } 
       
  1460 
       
  1461   private:
       
  1462 
       
  1463     typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> 
       
  1464     MapReaders;
       
  1465     
       
  1466     MapReaders areaders, breaders, readers;
       
  1467    
       
  1468     Graph& graph;
       
  1469     std::string name;
       
  1470     _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
       
  1471 
       
  1472     std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
       
  1473   };
       
  1474 
   985 
  1475 
   986   /// \ingroup section_io
  1476   /// \ingroup section_io
   987   /// \brief SectionReader for reading a graph's edgeset.
  1477   /// \brief SectionReader for reading a graph's edgeset.
   988   ///
  1478   ///
   989   /// The lemon format can store multiple graph edgesets with several maps.
  1479   /// The lemon format can store multiple graph edgesets with several maps.