1.1 --- a/src/lemon/lemon_reader.h Sat May 14 17:37:33 2005 +0000
1.2 +++ b/src/lemon/lemon_reader.h Sat May 14 17:39:37 2005 +0000
1.3 @@ -18,9 +18,11 @@
1.4 ///\file
1.5 ///\brief Lemon Format reader.
1.6
1.7 +
1.8 #ifndef LEMON_LEMON_READER_H
1.9 #define LEMON_LEMON_READER_H
1.10
1.11 +
1.12 #include <iostream>
1.13 #include <fstream>
1.14 #include <string>
1.15 @@ -30,11 +32,61 @@
1.16 #include <memory>
1.17
1.18 #include <lemon/error.h>
1.19 +#include <lemon/graph_utils.h>
1.20 +#include <lemon/utility.h>
1.21 #include <lemon/bits/item_reader.h>
1.22
1.23
1.24 namespace lemon {
1.25
1.26 + namespace _reader_bits {
1.27 +
1.28 + template <typename T>
1.29 + bool operator<(T, T) {
1.30 + throw DataFormatError("Id is not comparable");
1.31 + }
1.32 +
1.33 + template <typename T>
1.34 + struct Less {
1.35 + bool operator()(const T& p, const T& q) const {
1.36 + return p < q;
1.37 + }
1.38 + };
1.39 +
1.40 + template <typename M1, typename M2>
1.41 + class WriteComposeMap {
1.42 + public:
1.43 + typedef True NeedCopy;
1.44 +
1.45 + typedef typename M2::Key Key;
1.46 + typedef typename M1::Value Value;
1.47 +
1.48 + WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
1.49 + : m1(_m1), m2(_m2) {}
1.50 +
1.51 + void set(const Key& key, const Value& value) {
1.52 + m1.set(m2[key], value);
1.53 + }
1.54 +
1.55 + private:
1.56 +
1.57 + typename SmartReference<M1>::Type m1;
1.58 + typename SmartConstReference<M2>::Type m2;
1.59 +
1.60 + };
1.61 +
1.62 + template <typename M1, typename M2>
1.63 + WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
1.64 + return WriteComposeMap<M1, M2>(m1, m2);
1.65 + }
1.66 +
1.67 + template <typename M1, typename M2>
1.68 + WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
1.69 + return WriteComposeMap<M1, M2>(m1, m2);
1.70 + }
1.71 +
1.72 + }
1.73 +
1.74 /// \ingroup io_group
1.75 /// \brief Lemon Format reader class.
1.76 ///
1.77 @@ -338,8 +390,6 @@
1.78 virtual InverterBase<_Item>* getInverter() {
1.79 return this;
1.80 }
1.81 -
1.82 -
1.83 };
1.84
1.85 template <typename _Item, typename _Map, typename _Reader>
1.86 @@ -349,13 +399,15 @@
1.87 typedef _Reader Reader;
1.88 typedef typename Reader::Value Value;
1.89 typedef _Map Map;
1.90 - typedef std::map<Value, Item> Inverse;
1.91 + typedef std::map<Value, Item,
1.92 + typename _reader_bits::template Less<Value> > Inverse;
1.93
1.94 - Map& map;
1.95 + typename SmartReference<Map>::Type map;
1.96 Reader reader;
1.97 Inverse inverse;
1.98
1.99 - MapReaderInverter(Map& _map, const Reader& _reader)
1.100 + MapReaderInverter(typename SmartParameter<Map>::Type _map,
1.101 + const Reader& _reader)
1.102 : map(_map), reader(_reader) {}
1.103
1.104 virtual ~MapReaderInverter() {}
1.105 @@ -382,7 +434,6 @@
1.106 throw DataFormatError("Invalid ID error");
1.107 }
1.108 }
1.109 -
1.110 };
1.111
1.112 template <typename _Item, typename _Reader>
1.113 @@ -391,7 +442,8 @@
1.114 typedef _Item Item;
1.115 typedef _Reader Reader;
1.116 typedef typename Reader::Value Value;
1.117 - typedef std::map<Value, Item> Inverse;
1.118 + typedef std::map<Value, Item,
1.119 + typename _reader_bits::template Less<Value> > Inverse;
1.120
1.121 Reader reader;
1.122
1.123 @@ -426,8 +478,6 @@
1.124 Inverse inverse;
1.125 };
1.126
1.127 - // Readers
1.128 -
1.129 template <typename _Item>
1.130 class ReaderBase {
1.131 public:
1.132 @@ -447,10 +497,11 @@
1.133 typedef typename Reader::Value Value;
1.134 typedef _Item Item;
1.135
1.136 - Map& map;
1.137 + typename SmartReference<Map>::Type map;
1.138 Reader reader;
1.139
1.140 - MapReader(Map& _map, const Reader& _reader)
1.141 + MapReader(typename SmartParameter<Map>::Type _map,
1.142 + const Reader& _reader)
1.143 : map(_map), reader(_reader) {}
1.144
1.145 virtual ~MapReader() {}
1.146 @@ -569,7 +620,8 @@
1.147 /// attach it into the given LemonReader. The nodeset reader will
1.148 /// add the readed nodes to the given Graph. The reader will read
1.149 /// the section when the \c section_id and the \c _id are the same.
1.150 - NodeSetReader(LemonReader& _reader, Graph& _graph,
1.151 + NodeSetReader(LemonReader& _reader,
1.152 + typename SmartParameter<Graph>::Type _graph,
1.153 const std::string& _id = std::string(),
1.154 const DefaultSkipper& _skipper = DefaultSkipper())
1.155 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
1.156 @@ -595,17 +647,43 @@
1.157 ///
1.158 /// Add a new node map reader command for the reader.
1.159 template <typename Map>
1.160 - NodeSetReader& readMap(std::string name, Map& map) {
1.161 - return readMap<typename Traits::
1.162 - template Reader<typename Map::Value>, Map>(name, map);
1.163 + NodeSetReader& readNodeMap(std::string name, Map& map) {
1.164 + return _readMap<
1.165 + typename Traits::template Reader<typename Map::Value>, Map,
1.166 + typename SmartParameter<Map>::Type>(name, map);
1.167 + }
1.168 +
1.169 + template <typename Map>
1.170 + NodeSetReader& readNodeMap(std::string name, const Map& map) {
1.171 + return _readMap<
1.172 + typename Traits::template Reader<typename Map::Value>, Map,
1.173 + typename SmartParameter<Map>::Type>(name, map);
1.174 }
1.175
1.176 /// \brief Add a new node map reader command for the reader.
1.177 ///
1.178 /// Add a new node map reader command for the reader.
1.179 template <typename Reader, typename Map>
1.180 - NodeSetReader& readMap(std::string name, Map& map,
1.181 - const Reader& reader = Reader()) {
1.182 + NodeSetReader& readNodeMap(std::string name, Map& map,
1.183 + const Reader& reader = Reader()) {
1.184 + return _readMap<
1.185 + typename Traits::template Reader<typename Map::Value>, Map,
1.186 + typename SmartParameter<Map>::Type>(name, map, reader);
1.187 + }
1.188 +
1.189 + template <typename Reader, typename Map>
1.190 + NodeSetReader& readNodeMap(std::string name, const Map& map,
1.191 + const Reader& reader = Reader()) {
1.192 + return _readMap<
1.193 + typename Traits::template Reader<typename Map::Value>, Map,
1.194 + typename SmartParameter<Map>::Type>(name, map, reader);
1.195 + }
1.196 +
1.197 + private:
1.198 +
1.199 + template <typename Reader, typename Map, typename MapParameter>
1.200 + NodeSetReader& _readMap(std::string name, MapParameter map,
1.201 + const Reader& reader = Reader()) {
1.202 if (readers.find(name) != readers.end()) {
1.203 ErrorMessage msg;
1.204 msg << "Multiple read rule for node map: " << name;
1.205 @@ -616,11 +694,13 @@
1.206 return *this;
1.207 }
1.208
1.209 + public:
1.210 +
1.211 /// \brief Add a new node map skipper command for the reader.
1.212 ///
1.213 /// Add a new node map skipper command for the reader.
1.214 template <typename Reader>
1.215 - NodeSetReader& skipMap(std::string name,
1.216 + NodeSetReader& skipNodeMap(std::string name,
1.217 const Reader& reader = Reader()) {
1.218 if (readers.find(name) != readers.end()) {
1.219 ErrorMessage msg;
1.220 @@ -636,7 +716,7 @@
1.221 /// \brief Gives back true when the SectionReader can process
1.222 /// the section with the given header line.
1.223 ///
1.224 - /// It gives back true when the header line starts with \c @nodeset,
1.225 + /// It gives back true when the header line starts with \c \@nodeset,
1.226 /// and the header line's id and the nodeset's id are the same.
1.227 virtual bool header(const std::string& line) {
1.228 std::istringstream ls(line);
1.229 @@ -690,7 +770,7 @@
1.230 ///
1.231 /// It reads an id from the stream and gives back which node belongs to
1.232 /// it. It is possible only if there was read an "id" named map.
1.233 - typename Graph::Node readId(std::istream& is) const {
1.234 + Item readId(std::istream& is) const {
1.235 return inverter->read(is);
1.236 }
1.237
1.238 @@ -699,7 +779,7 @@
1.239 typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
1.240 MapReaders readers;
1.241
1.242 - Graph& graph;
1.243 + typename SmartReference<Graph>::Type graph;
1.244 std::string id;
1.245 SkipReader<Item, DefaultSkipper> skipper;
1.246
1.247 @@ -714,8 +794,9 @@
1.248 /// \c edgeset_id may be empty.
1.249 ///
1.250 /// The first line of the section contains the names of the maps separated
1.251 - /// with white spaces. Each next lines describes a node in the nodeset. The
1.252 - /// line contains the two nodes' id and the mapped values for each map.
1.253 + /// with white spaces. Each next lines describes an edge in the edgeset. The
1.254 + /// line contains the source and the target nodes' id and the mapped
1.255 + /// values for each map.
1.256 ///
1.257 /// If the edgeset contains an \c "id" named map then it will be regarded
1.258 /// as id map. This map should contain only unique values and when the
1.259 @@ -746,7 +827,8 @@
1.260 /// The reader will read the section only if the \c _id and the
1.261 /// \c edgset_id are the same.
1.262 template <typename NodeIdReader>
1.263 - EdgeSetReader(LemonReader& _reader, Graph& _graph,
1.264 + EdgeSetReader(LemonReader& _reader,
1.265 + typename SmartParameter<Graph>::Type _graph,
1.266 const NodeIdReader& _nodeIdReader,
1.267 const std::string& _id = std::string(),
1.268 const DefaultSkipper& _skipper = DefaultSkipper())
1.269 @@ -774,17 +856,43 @@
1.270 ///
1.271 /// Add a new edge map reader command for the reader.
1.272 template <typename Map>
1.273 - EdgeSetReader& readMap(std::string name, Map& map) {
1.274 - return readMap<typename Traits::
1.275 - template Reader<typename Map::Value>, Map>(name, map);
1.276 + EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1.277 + return _readMap<
1.278 + typename Traits::template Reader<typename Map::Value>, Map,
1.279 + typename SmartParameter<Map>::Type>(name, map);
1.280 + }
1.281 +
1.282 + template <typename Map>
1.283 + EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1.284 + return _readMap<
1.285 + typename Traits::template Reader<typename Map::Value>, Map,
1.286 + typename SmartParameter<Map>::Type>(name, map);
1.287 }
1.288
1.289 /// \brief Add a new edge map reader command for the reader.
1.290 ///
1.291 /// Add a new edge map reader command for the reader.
1.292 template <typename Reader, typename Map>
1.293 - EdgeSetReader& readMap(std::string name, Map& map,
1.294 - const Reader& reader = Reader()) {
1.295 + EdgeSetReader& readEdgeMap(std::string name, Map& map,
1.296 + const Reader& reader = Reader()) {
1.297 + return _readMap<
1.298 + typename Traits::template Reader<typename Map::Value>, Map,
1.299 + typename SmartParameter<Map>::Type>(name, map, reader);
1.300 + }
1.301 +
1.302 + template <typename Reader, typename Map>
1.303 + EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1.304 + const Reader& reader = Reader()) {
1.305 + return _readMap<
1.306 + typename Traits::template Reader<typename Map::Value>, Map,
1.307 + typename SmartParameter<Map>::Type>(name, map, reader);
1.308 + }
1.309 +
1.310 + private:
1.311 +
1.312 + template <typename Reader, typename Map, typename MapParameter>
1.313 + EdgeSetReader& _readMap(std::string name, MapParameter map,
1.314 + const Reader& reader = Reader()) {
1.315 if (readers.find(name) != readers.end()) {
1.316 ErrorMessage msg;
1.317 msg << "Multiple read rule for edge map: " << name;
1.318 @@ -795,15 +903,17 @@
1.319 return *this;
1.320 }
1.321
1.322 + public:
1.323 +
1.324 /// \brief Add a new edge map skipper command for the reader.
1.325 ///
1.326 /// Add a new edge map skipper command for the reader.
1.327 template <typename Reader>
1.328 - EdgeSetReader& skipMap(std::string name,
1.329 - const Reader& reader = Reader()) {
1.330 + EdgeSetReader& skipEdgeMap(std::string name,
1.331 + const Reader& reader = Reader()) {
1.332 if (readers.find(name) != readers.end()) {
1.333 ErrorMessage msg;
1.334 - msg << "Multiple read rule for node map: " << name;
1.335 + msg << "Multiple read rule for edge map: " << name;
1.336 throw IOParameterError(msg.message());
1.337 }
1.338 readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
1.339 @@ -815,7 +925,7 @@
1.340 /// \brief Gives back true when the SectionReader can process
1.341 /// the section with the given header line.
1.342 ///
1.343 - /// It gives back true when the header line starts with \c @edgeset,
1.344 + /// It gives back true when the header line starts with \c \@edgeset,
1.345 /// and the header line's id and the edgeset's id are the same.
1.346 virtual bool header(const std::string& line) {
1.347 std::istringstream ls(line);
1.348 @@ -871,7 +981,7 @@
1.349 ///
1.350 /// It reads an id from the stream and gives back which edge belongs to
1.351 /// it. It is possible only if there was read an "id" named map.
1.352 - typename Graph::Edge readId(std::istream& is) const {
1.353 + Item readId(std::istream& is) const {
1.354 return inverter->read(is);
1.355 }
1.356
1.357 @@ -880,7 +990,281 @@
1.358 typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
1.359 MapReaders readers;
1.360
1.361 - Graph& graph;
1.362 + typename SmartReference<Graph>::Type graph;
1.363 + std::string id;
1.364 + SkipReader<Item, DefaultSkipper> skipper;
1.365 +
1.366 + std::auto_ptr<InverterBase<Item> > inverter;
1.367 + std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
1.368 + };
1.369 +
1.370 + /// \ingroup io_group
1.371 + /// \brief SectionReader for reading a undirected graph's edgeset.
1.372 + ///
1.373 + /// The lemon format can store multiple undirected edgesets with several
1.374 + /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1.375 + /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1.376 + ///
1.377 + /// The first line of the section contains the names of the maps separated
1.378 + /// with white spaces. Each next lines describes an edge in the edgeset. The
1.379 + /// line contains the connected nodes' id and the mapped values for each map.
1.380 + ///
1.381 + /// The section can handle the directed as a syntactical sugar. Two
1.382 + /// undirected edge map describes one directed edge map. This two maps
1.383 + /// are the forward map and the backward map and the names of this map
1.384 + /// is near the same just with a prefix \c '+' or \c '-' character
1.385 + /// difference.
1.386 + ///
1.387 + /// If the edgeset contains an \c "id" named map then it will be regarded
1.388 + /// as id map. This map should contain only unique values and when the
1.389 + /// \c readId() member will read a value from the given stream it will
1.390 + /// give back that undiricted edge which is mapped to this value.
1.391 + ///
1.392 + /// The undirected edgeset reader needs a node id reader to identify which
1.393 + /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1.394 + /// it will be able to resolve the nodes by ids.
1.395 + ///
1.396 + /// \relates LemonReader
1.397 + template <typename _Graph, typename _Traits = DefaultReaderTraits>
1.398 + class UndirEdgeSetReader : public CommonSectionReaderBase {
1.399 + typedef CommonSectionReaderBase Parent;
1.400 + public:
1.401 +
1.402 + typedef _Graph Graph;
1.403 + typedef _Traits Traits;
1.404 + typedef typename Graph::UndirEdge Item;
1.405 + typedef typename Traits::Skipper DefaultSkipper;
1.406 +
1.407 + /// \brief Constructor.
1.408 + ///
1.409 + /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1.410 + /// and attach it into the given LemonReader. The undirected edgeset
1.411 + /// reader will add the readed undirected edges to the given Graph. It
1.412 + /// will use the given node id reader to read the source and target
1.413 + /// nodes of the edges. The reader will read the section only if the
1.414 + /// \c _id and the \c undiredgset_id are the same.
1.415 + template <typename NodeIdReader>
1.416 + UndirEdgeSetReader(LemonReader& _reader,
1.417 + typename SmartParameter<Graph>::Type _graph,
1.418 + const NodeIdReader& _nodeIdReader,
1.419 + const std::string& _id = std::string(),
1.420 + const DefaultSkipper& _skipper = DefaultSkipper())
1.421 + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
1.422 + nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
1.423 + (_nodeIdReader)) {}
1.424 +
1.425 + /// \brief Destructor.
1.426 + ///
1.427 + /// Destructor for UndirEdgeSetReader.
1.428 + virtual ~UndirEdgeSetReader() {
1.429 + for (typename MapReaders::iterator it = readers.begin();
1.430 + it != readers.end(); ++it) {
1.431 + delete it->second;
1.432 + }
1.433 + }
1.434 +
1.435 + private:
1.436 + UndirEdgeSetReader(const UndirEdgeSetReader&);
1.437 + void operator=(const UndirEdgeSetReader&);
1.438 +
1.439 + public:
1.440 +
1.441 + /// \brief Add a new undirected edge map reader command for the reader.
1.442 + ///
1.443 + /// Add a new edge undirected map reader command for the reader.
1.444 + template <typename Map>
1.445 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1.446 + return _readMap<
1.447 + typename Traits::template Reader<typename Map::Value>, Map,
1.448 + typename SmartParameter<Map>::Type>(name, map);
1.449 + }
1.450 +
1.451 + template <typename Map>
1.452 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1.453 + return _readMap<
1.454 + typename Traits::template Reader<typename Map::Value>, Map,
1.455 + typename SmartParameter<Map>::Type>(name, map);
1.456 + }
1.457 +
1.458 + /// \brief Add a new undirected edge map reader command for the reader.
1.459 + ///
1.460 + /// Add a new edge undirected map reader command for the reader.
1.461 + template <typename Reader, typename Map>
1.462 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1.463 + const Reader& reader = Reader()) {
1.464 + return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1.465 + (name, map, reader);
1.466 + }
1.467 +
1.468 + template <typename Reader, typename Map>
1.469 + UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1.470 + const Reader& reader = Reader()) {
1.471 + return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
1.472 + (name, map, reader);
1.473 + }
1.474 +
1.475 + private:
1.476 +
1.477 + template <typename Reader, typename Map, typename MapParameter>
1.478 + UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1.479 + const Reader& reader = Reader()) {
1.480 + if (readers.find(name) != readers.end()) {
1.481 + ErrorMessage msg;
1.482 + msg << "Multiple read rule for edge map: " << name;
1.483 + throw IOParameterError(msg.message());
1.484 + }
1.485 + readers.insert(
1.486 + make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
1.487 + return *this;
1.488 + }
1.489 +
1.490 + public:
1.491 +
1.492 + /// \brief Add a new undirected edge map skipper command for the reader.
1.493 + ///
1.494 + /// Add a new undirected edge map skipper command for the reader.
1.495 + template <typename Reader>
1.496 + UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1.497 + const Reader& reader = Reader()) {
1.498 + if (readers.find(name) != readers.end()) {
1.499 + ErrorMessage msg;
1.500 + msg << "Multiple read rule for node map: " << name;
1.501 + throw IOParameterError(msg.message());
1.502 + }
1.503 + readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
1.504 + return *this;
1.505 + }
1.506 +
1.507 + /// \brief Add a new directed edge map reader command for the reader.
1.508 + ///
1.509 + /// Add a new directed edge map reader command for the reader.
1.510 + template <typename Map>
1.511 + UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1.512 + return _readDirMap<
1.513 + typename Traits::template Reader<typename Map::Value>, Map,
1.514 + typename SmartParameter<Map>::Type>(name, map);
1.515 + }
1.516 +
1.517 + template <typename Map>
1.518 + UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1.519 + return _readDirMap<
1.520 + typename Traits::template Reader<typename Map::Value>, Map,
1.521 + typename SmartParameter<Map>::Type>(name, map);
1.522 + }
1.523 +
1.524 + /// \brief Add a new directed edge map reader command for the reader.
1.525 + ///
1.526 + /// Add a new directed edge map reader command for the reader.
1.527 + template <typename Reader, typename Map>
1.528 + UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1.529 + const Reader& reader = Reader()) {
1.530 + return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1.531 + (name, map, reader);
1.532 + }
1.533 +
1.534 + template <typename Reader, typename Map>
1.535 + UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1.536 + const Reader& reader = Reader()) {
1.537 + return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1.538 + (name, map, reader);
1.539 + }
1.540 +
1.541 + private:
1.542 +
1.543 + template <typename Reader, typename Map, typename MapParameter>
1.544 + UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1.545 + const Reader& reader = Reader()) {
1.546 + readMap("+" + name,
1.547 + _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
1.548 + readMap("-" + name,
1.549 + _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
1.550 + return *this;
1.551 + }
1.552 +
1.553 + public:
1.554 +
1.555 + /// \brief Add a new directed edge map skipper command for the reader.
1.556 + ///
1.557 + /// Add a new directed edge map skipper command for the reader.
1.558 + template <typename Reader>
1.559 + UndirEdgeSetReader& skipEdgeMap(std::string name,
1.560 + const Reader& reader = Reader()) {
1.561 + skipMap("+" + name, reader);
1.562 + skipMap("-" + name, reader);
1.563 + return *this;
1.564 + }
1.565 +
1.566 + protected:
1.567 +
1.568 + /// \brief Gives back true when the SectionReader can process
1.569 + /// the section with the given header line.
1.570 + ///
1.571 + /// It gives back true when the header line starts with \c \@undiredgeset,
1.572 + /// and the header line's id and the edgeset's id are the same.
1.573 + virtual bool header(const std::string& line) {
1.574 + std::istringstream ls(line);
1.575 + std::string command;
1.576 + std::string name;
1.577 + ls >> command >> name;
1.578 + return command == "@undiredgeset" && name == id;
1.579 + }
1.580 +
1.581 + /// \brief Reader function of the section.
1.582 + ///
1.583 + /// It reads the content of the section.
1.584 + virtual void read(std::istream& is) {
1.585 + std::vector<ReaderBase<Item>* > index;
1.586 + std::string line;
1.587 +
1.588 + getline(is, line);
1.589 + std::istringstream ls(line);
1.590 + while (ls >> id) {
1.591 + typename MapReaders::iterator it = readers.find(id);
1.592 + if (it != readers.end()) {
1.593 + index.push_back(it->second);
1.594 + } else {
1.595 + index.push_back(&skipper);
1.596 + }
1.597 + if (id == "id" && inverter.get() == 0) {
1.598 + inverter.reset(index.back()->getInverter());
1.599 + index.back() = inverter.get();
1.600 + }
1.601 + }
1.602 + while (getline(is, line)) {
1.603 + std::istringstream ls(line);
1.604 + typename Graph::Node from = nodeIdReader->read(ls);
1.605 + typename Graph::Node to = nodeIdReader->read(ls);
1.606 + typename Graph::UndirEdge edge = graph.addEdge(from, to);
1.607 + for (int i = 0; i < (int)index.size(); ++i) {
1.608 + index[i]->read(ls, edge);
1.609 + }
1.610 + }
1.611 + }
1.612 +
1.613 + public:
1.614 +
1.615 + /// \brief Returns true if the edgeset can give back the edge by its id.
1.616 + ///
1.617 + /// Returns true if the edgeset can give back the undirected edge by its
1.618 + /// id. It is possible only if an "id" named map was read.
1.619 + bool isIdReader() const {
1.620 + return inverter.get() != 0;
1.621 + }
1.622 +
1.623 + /// \brief Gives back the undirected edge by its id.
1.624 + ///
1.625 + /// It reads an id from the stream and gives back which undirected edge
1.626 + /// belongs to it. It is possible only if there was read an "id" named map.
1.627 + Item readId(std::istream& is) const {
1.628 + return inverter->read(is);
1.629 + }
1.630 +
1.631 + private:
1.632 +
1.633 + typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
1.634 + MapReaders readers;
1.635 +
1.636 + typename SmartReference<Graph>::Type graph;
1.637 std::string id;
1.638 SkipReader<Item, DefaultSkipper> skipper;
1.639
1.640 @@ -945,7 +1329,7 @@
1.641 /// \brief Gives back true when the SectionReader can process
1.642 /// the section with the given header line.
1.643 ///
1.644 - /// It gives back true when the header line start with \c @nodes,
1.645 + /// It gives back true when the header line start with \c \@nodes,
1.646 /// and the header line's id and the reader's id are the same.
1.647 virtual bool header(const std::string& line) {
1.648 std::istringstream ls(line);
1.649 @@ -1002,7 +1386,7 @@
1.650 /// Constructor for EdgeReader. It creates the EdgeReader and
1.651 /// attach it into the given LemonReader. It will use the given
1.652 /// edge id reader to give back the edges. The reader will read the
1.653 - /// section only if the \c _id and the \c nodes_id are the same.
1.654 + /// section only if the \c _id and the \c edges_id are the same.
1.655 template <typename _IdReader>
1.656 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1.657 const std::string& _id = std::string())
1.658 @@ -1036,7 +1420,100 @@
1.659 /// \brief Gives back true when the SectionReader can process
1.660 /// the section with the given header line.
1.661 ///
1.662 - /// It gives back true when the header line start with \c @edges,
1.663 + /// It gives back true when the header line start with \c \@edges,
1.664 + /// and the header line's id and the reader's id are the same.
1.665 + virtual bool header(const std::string& line) {
1.666 + std::istringstream ls(line);
1.667 + std::string command;
1.668 + std::string name;
1.669 + ls >> command >> name;
1.670 + return command == "@edges" && name == id;
1.671 + }
1.672 +
1.673 + /// \brief Reader function of the section.
1.674 + ///
1.675 + /// It reads the content of the section.
1.676 + virtual void read(std::istream& is) {
1.677 + std::string line;
1.678 + while (getline(is, line)) {
1.679 + std::istringstream ls(line);
1.680 + std::string id;
1.681 + ls >> id;
1.682 + typename ItemReaders::iterator it = readers.find(id);
1.683 + if (it != readers.end()) {
1.684 + *(it->second) = idReader->read(ls);
1.685 + }
1.686 + }
1.687 + }
1.688 +
1.689 + private:
1.690 +
1.691 + std::string id;
1.692 +
1.693 + typedef std::map<std::string, Item*> ItemReaders;
1.694 + ItemReaders readers;
1.695 + std::auto_ptr<IdReaderBase<Item> > idReader;
1.696 + };
1.697 +
1.698 + /// \ingroup io_group
1.699 + /// \brief SectionReader for reading labeled undirected edges.
1.700 + ///
1.701 + /// The undirected edges section's header line is \c \@undiredges
1.702 + /// \c undiredges_id, but the \c undiredges_id may be empty.
1.703 + ///
1.704 + /// Each line in the section contains the name of the undirected edge
1.705 + /// and then the undirected edge id.
1.706 + ///
1.707 + /// \relates LemonReader
1.708 + template <typename _Graph>
1.709 + class UndirEdgeReader : public CommonSectionReaderBase {
1.710 + typedef CommonSectionReaderBase Parent;
1.711 + typedef _Graph Graph;
1.712 + typedef typename Graph::UndirEdge Item;
1.713 + public:
1.714 +
1.715 + /// \brief Constructor.
1.716 + ///
1.717 + /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1.718 + /// attach it into the given LemonReader. It will use the given
1.719 + /// undirected edge id reader to give back the edges. The reader will
1.720 + /// read the section only if the \c _id and the \c undiredges_id are
1.721 + /// the same.
1.722 + template <typename _IdReader>
1.723 + UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1.724 + const std::string& _id = std::string())
1.725 + : Parent(_reader), id(_id),
1.726 + idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
1.727 + {}
1.728 +
1.729 + /// \brief Destructor.
1.730 + ///
1.731 + /// Destructor for UndirEdgeReader.
1.732 + virtual ~UndirEdgeReader() {}
1.733 + private:
1.734 + UndirEdgeReader(const UndirEdgeReader&);
1.735 + void operator=(const UndirEdgeReader&);
1.736 +
1.737 + public:
1.738 +
1.739 + /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1.740 + ///
1.741 + /// Add an undirected edge reader command for the UndirEdgeReader.
1.742 + void readUndirEdge(const std::string& name, Item& item) {
1.743 + if (readers.find(name) != readers.end()) {
1.744 + ErrorMessage msg;
1.745 + msg << "Multiple read rule for edge: " << name;
1.746 + throw IOParameterError(msg.message());
1.747 + }
1.748 + readers.insert(make_pair(name, &item));
1.749 + }
1.750 +
1.751 + protected:
1.752 +
1.753 + /// \brief Gives back true when the SectionReader can process
1.754 + /// the section with the given header line.
1.755 + ///
1.756 + /// It gives back true when the header line start with \c \@edges,
1.757 /// and the header line's id and the reader's id are the same.
1.758 virtual bool header(const std::string& line) {
1.759 std::istringstream ls(line);
1.760 @@ -1141,7 +1618,7 @@
1.761 /// \brief Gives back true when the SectionReader can process
1.762 /// the section with the given header line.
1.763 ///
1.764 - /// It gives back true when the header line start with \c @attributes,
1.765 + /// It gives back true when the header line start with \c \@attributes,
1.766 /// and the header line's id and the attributeset's id are the same.
1.767 bool header(const std::string& line) {
1.768 std::istringstream ls(line);
1.769 @@ -1174,6 +1651,5 @@
1.770 Readers readers;
1.771 };
1.772
1.773 -
1.774 }
1.775 #endif