Changeset 1409:d2d1f8fa187b in lemon-0.x
- Timestamp:
- 05/11/05 13:50:13 (20 years ago)
- Branch:
- default
- Phase:
- public
- Convert:
- svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1876
- Location:
- src/lemon
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/lemon/Makefile.am
r1408 r1409 54 54 utility.h \ 55 55 lemon_reader.h \ 56 lemon_writer.h \ 56 57 graph_reader.h \ 57 58 graph_writer.h \ … … 67 68 bits/erasable_graph_extender.h \ 68 69 bits/undir_graph_extender.h \ 69 bits/item_reader.h 70 bits/item_reader.h \ 71 bits/item_writer.h 70 72 71 73 noinst_HEADERS = \ -
src/lemon/graph_writer.h
r1402 r1409 23 23 24 24 #include <iostream> 25 #include <sstream> 26 27 #include <map> 28 #include <vector> 29 30 #include <memory> 31 32 #include <lemon/graph_utils.h> 33 34 #include <lemon/invalid.h> 25 35 26 #include <lemon/error.h> 36 27 #include <lemon/lemon_writer.h> 37 28 38 29 namespace lemon { … … 41 32 /// @{ 42 33 43 /// \brief Standard WriterTraits for the GraphWriter class.44 ///45 /// Standard WriterTraits for the GraphWriter class.46 /// It defines standard writing method for all type of value.47 /// \author Balazs Dezso48 struct DefaultWriterTraits {49 50 /// \brief Template class for writing an value.51 ///52 /// Template class for writing an value.53 /// \author Balazs Dezso54 template <typename _Value>55 struct Writer {56 /// The value type.57 typedef _Value Value;58 59 /// \brief Writes a value to the given stream.60 ///61 /// Writes a value to the given stream.62 void write(std::ostream& os, const Value& value) {63 os << value << '\t';64 }65 };66 67 /// \brief Returns wheter this name is an ID map name.68 ///69 /// Returns wheter this name is an ID map name.70 static bool idMapName(const std::string& name) {71 return name == "id";72 }73 74 };75 76 77 /// \brief Writer class for quoted strings.78 ///79 /// Writer class for quoted strings. It can process the escape80 /// sequences in the string.81 /// \author Balazs Dezso82 class QuotedStringWriter {83 public:84 typedef std::string Value;85 86 /// \brief Constructor for the writer.87 ///88 /// Constructor for the writer. If the given parameter is true89 /// the writer creates escape sequences from special characters.90 QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}91 92 /// \brief Writes a quoted string to the given stream.93 ///94 /// Writes a quoted string to the given stream.95 void write(std::ostream& os, const std::string& value) {96 os << "\"";97 if (escaped) {98 std::ostringstream ls;99 for (int i = 0; i < (int)value.size(); ++i) {100 writeEscape(ls, value[i]);101 }102 os << ls.str();103 } else {104 os << value;105 }106 os << "\"";107 }108 109 private:110 111 static void writeEscape(std::ostream& os, char c) {112 switch (c) {113 case '\\':114 os << "\\\\";115 return;116 case '\"':117 os << "\\\"";118 return;119 case '\'':120 os << "\\\'";121 return;122 case '\?':123 os << "\\\?";124 return;125 case '\a':126 os << "\\a";127 return;128 case '\b':129 os << "\\b";130 return;131 case '\f':132 os << "\\f";133 return;134 case '\r':135 os << "\\r";136 return;137 case '\n':138 os << "\\n";139 return;140 case '\t':141 os << "\\t";142 return;143 case '\v':144 os << "\\v";145 return;146 default:147 if (c < 0x20) {148 os << '\\' << std::oct << (int)c;149 } else {150 os << c;151 }152 return;153 }154 }155 private:156 bool escaped;157 };158 159 class GUIWriter {160 public:161 virtual void write(std::ostream& os) = 0;162 };163 164 165 34 /// \brief The graph writer class. 166 35 /// … … 232 101 typedef _Graph Graph; 233 102 typedef typename Graph::Node Node; 234 typedef typename Graph::NodeIt NodeIt;235 103 typedef typename Graph::Edge Edge; 236 typedef typename Graph::EdgeIt EdgeIt;237 104 238 105 typedef _WriterTraits WriterTraits; 239 106 240 107 /// \brief Construct a new GraphWriter. 241 108 /// 242 /// Construct a new GraphWriter. It writes from the given map, 243 /// it constructs the given map and it use the given writer as the 244 /// default skipper. 109 /// Construct a new GraphWriter. It writes the given graph 110 /// to the given stream. 245 111 GraphWriter(std::ostream& _os, const Graph& _graph) 246 : gui_writer(0), os(_os), graph(_graph){} 247 112 : writer(new LemonWriter(_os)), own_writer(true), 113 graph(_graph), 114 nodeset_writer(*writer, graph, std::string()), 115 edgeset_writer(*writer, graph, nodeset_writer, std::string()), 116 node_writer(*writer, nodeset_writer, std::string()), 117 edge_writer(*writer, edgeset_writer, std::string()), 118 attribute_writer(*writer, std::string()) {} 119 120 /// \brief Construct a new GraphWriter. 121 /// 122 /// Construct a new GraphWriter. It writes into the given graph 123 /// to the given file. 124 GraphWriter(const std::string& _filename, const Graph& _graph) 125 : writer(new LemonWriter(_filename)), own_writer(true), 126 graph(_graph), 127 nodeset_writer(*writer, graph, std::string(), skipper), 128 edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper), 129 node_writer(*writer, nodeset_writer, std::string()), 130 edge_writer(*writer, edgeset_writer, std::string()), 131 attribute_writer(*writer, std::string()) {} 132 133 /// \brief Construct a new GraphWriter. 134 /// 135 /// Construct a new GraphWriter. It writes into the given graph 136 /// to given LemonReader. 137 GraphWriter(LemonWriter& _writer, const Graph& _graph) 138 : writer(_writer), own_writer(false), 139 graph(_graph), 140 nodeset_writer(*writer, graph, std::string()), 141 edgeset_writer(*writer, graph, nodeset_writer, std::string()), 142 node_writer(*writer, nodeset_writer, std::string()), 143 edge_writer(*writer, edgeset_writer, std::string()), 144 attribute_writer(*writer, std::string()) {} 248 145 249 146 /// \brief Destruct the graph writer. … … 251 148 /// Destruct the graph writer. 252 149 ~GraphWriter() { 253 for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 254 it != node_map_writers.end(); ++it) { 255 delete it->second; 256 } 257 258 for (typename EdgeMapWriters::iterator it = edge_map_writers.begin(); 259 it != edge_map_writers.end(); ++it) { 260 delete it->second; 261 } 262 263 } 264 265 // Node map rules 150 if (own_writer) 151 delete writer; 152 } 266 153 267 154 /// \brief Add a new node map writer command for the writer. … … 270 157 template <typename Map> 271 158 GraphWriter& writeNodeMap(std::string name, const Map& map) { 272 return writeNodeMap<typename WriterTraits::template Writer<273 typename Map::Value>, Map>(name, map);159 nodeset_writer.writeMap(name, map); 160 return *this; 274 161 } 275 162 … … 279 166 template <typename Writer, typename Map> 280 167 GraphWriter& writeNodeMap(std::string name, const Map& map, 281 const Writer& writer = Writer()) { 282 node_map_writers.push_back( 283 make_pair(name, new MapWriter<Node, Map, Writer>(map, writer))); 284 return *this; 285 } 286 287 // Edge map rules 168 const Writer& writer = Writer()) { 169 nodeset_writer.writeMap(name, map, writer); 170 return *this; 171 } 172 288 173 289 174 /// \brief Add a new edge map writer command for the writer. … … 292 177 template <typename Map> 293 178 GraphWriter& writeEdgeMap(std::string name, const Map& map) { 294 return writeEdgeMap<typename WriterTraits::template Writer<295 typename Map::Value>, Map>(name, map);179 edgeset_writer.writeMap(name, map); 180 return *this; 296 181 } 297 182 … … 301 186 /// Add a new edge map writer command for the writer. 302 187 template <typename Writer, typename Map> 303 GraphWriter& writeEdgeMap(std::string name, 304 const Map& map, const Writer& writer = Writer()) { 305 edge_map_writers.push_back(make_pair(name, 306 new MapWriter<Edge, Map, Writer>(map, writer))); 188 GraphWriter& writeEdgeMap(std::string name, const Map& map, 189 const Writer& writer = Writer()) { 190 edgeset_writer.writeMap(name, map, writer); 307 191 return *this; 308 192 } … … 312 196 /// Add a new labeled node writer for the writer. 313 197 GraphWriter& writeNode(std::string name, const Node& node) { 314 node_writer s.push_back(make_pair(name, node));198 node_writer.writeNode(name, node); 315 199 return *this; 316 200 } … … 320 204 /// Add a new labeled edge writer for the writer. 321 205 GraphWriter& writeEdge(std::string name, const Edge& edge) { 322 edge_writers.push_back(make_pair(name, edge)); 323 return *this; 324 } 325 326 GraphWriter& writeGUI(const GUIWriter& writer) { 327 gui_writer = &writer; 206 edge_writer.writeEdge(name, edge); 207 } 208 209 /// \brief Add a new attribute writer command. 210 /// 211 /// Add a new attribute writer command. 212 template <typename Value> 213 GraphWriter& writeAttribute(std::string name, const Value& value) { 214 attribute_writer.writeAttribute(name, value); 215 return *this; 216 } 217 218 /// \brief Add a new attribute writer command. 219 /// 220 /// Add a new attribute writer command. 221 template <typename Writer, typename Value> 222 GraphWriter& writeAttribute(std::string name, const Value& value, 223 const Writer& writer) { 224 attribute_writer.writeAttribute<Writer>(name, value, writer); 225 return *this; 226 } 227 228 /// \brief Conversion operator to LemonWriter. 229 /// 230 /// Conversion operator to LemonWriter. It make possible 231 /// to access the encapsulated \e LemonWriter, this way 232 /// you can attach to this writer new instances of 233 /// \e LemonWriter::SectionWriter. 234 operator LemonWriter&() { 235 return *writer; 328 236 } 329 237 … … 331 239 /// 332 240 /// Executes the writer commands. 333 void run() { 334 WriterBase<Node>* nodeWriter = 0; 335 WriterBase<Edge>* edgeWriter = 0; 336 writeNodeSet(nodeWriter); 337 writeEdgeSet(nodeWriter, edgeWriter); 338 writeNodes(nodeWriter); 339 writeEdges(edgeWriter); 340 writeGUI(); 341 os << "@end" << std::endl; 241 void run() { 242 writer->run(); 342 243 } 343 244 344 245 private: 345 246 346 template <class _Item> 347 class WriterBase { 348 public: 349 typedef _Item Item; 350 virtual void write(std::ostream&, const Item&) = 0; 351 }; 352 353 template <class _Item, typename _Map, typename _Writer> 354 class MapWriter : public WriterBase<_Item> { 355 public: 356 typedef _Map Map; 357 typedef _Writer Writer; 358 typedef typename Writer::Value Value; 359 typedef _Item Item; 360 361 const Map& map; 362 Writer writer; 363 364 MapWriter(const Map& _map, const Writer& _writer) 365 : map(_map), writer(_writer) {} 366 367 368 virtual void write(std::ostream& os, const Item& item) { 369 writer.write(os, map[item]); 370 } 371 372 }; 373 374 void writeNodeSet(WriterBase<Node>* & nodeWriter) { 375 if (node_map_writers.size() == 0) return; 376 os << "@nodeset" << std::endl; 377 for (int i = 0; i < (int)node_map_writers.size(); ++i) { 378 const std::string& id = node_map_writers[i].first; 379 os << id << '\t'; 380 if (WriterTraits::idMapName(id) && nodeWriter == 0) { 381 nodeWriter = node_map_writers[i].second; 382 } 383 } 384 os << std::endl; 385 for (NodeIt it(graph); it != INVALID; ++it) { 386 for (int i = 0; i < (int)node_map_writers.size(); ++i) { 387 node_map_writers[i].second->write(os, it); 388 } 389 os << std::endl; 390 } 391 392 } 393 394 void writeEdgeSet(WriterBase<Node>* nodeWriter, 395 WriterBase<Edge>* & edgeWriter) { 396 if (edge_map_writers.size() == 0) return; 397 if (nodeWriter == 0) { 398 throw DataFormatError("Cannot find node id map"); 399 } 400 os << "@edgeset" << std::endl; 401 os << "\t\t"; 402 for (int i = 0; i < (int)edge_map_writers.size(); ++i) { 403 const std::string& id = edge_map_writers[i].first; 404 os << id << '\t'; 405 if (WriterTraits::idMapName(id) && edgeWriter == 0) { 406 edgeWriter = edge_map_writers[i].second; 407 } 408 } 409 os << std::endl; 410 for (EdgeIt it(graph); it != INVALID; ++it) { 411 nodeWriter->write(os, graph.source(it)); 412 nodeWriter->write(os, graph.target(it)); 413 for (int i = 0; i < (int)edge_map_writers.size(); ++i) { 414 edge_map_writers[i].second->write(os, it); 415 } 416 os << std::endl; 417 } 418 } 419 420 void writeNodes(WriterBase<Node>* nodeWriter) { 421 if (node_writers.size() == 0) return; 422 if (nodeWriter == 0) { 423 throw DataFormatError("Cannot find node id map"); 424 } 425 os << "@nodes" << std::endl; 426 for (int i = 0; i < (int)node_writers.size(); ++i) { 427 os << node_writers[i].first << '\t'; 428 nodeWriter->write(os, node_writers[i].second); 429 os << std::endl; 430 } 431 } 432 433 void writeEdges(WriterBase<Edge>* edgeWriter) { 434 if (edge_writers.size() == 0) return; 435 if (edgeWriter == 0) { 436 throw DataFormatError("Cannot find node id map"); 437 } 438 os << "@edges" << std::endl; 439 for (int i = 0; i < (int)edge_writers.size(); ++i) { 440 os << edge_writers[i].first << '\t'; 441 edgeWriter->write(os, edge_writers[i].second); 442 os << std::endl; 443 } 444 } 247 LemonWriter* writer; 248 bool own_writer; 249 250 const Graph& graph; 251 252 NodeSetWriter<Graph, WriterTraits> nodeset_writer; 253 EdgeSetWriter<Graph, WriterTraits> edgeset_writer; 254 255 NodeWriter<Graph> node_writer; 256 EdgeWriter<Graph> edge_writer; 445 257 446 void writeGUI() { 447 if (gui_writer) { 448 os << "@gui" << std::endl; 449 gui_writer->write(os); 450 } 451 } 452 453 454 455 typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 456 NodeMapWriters; 457 NodeMapWriters node_map_writers; 458 459 typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 460 EdgeMapWriters; 461 EdgeMapWriters edge_map_writers; 462 463 typedef std::vector<std::pair<std::string, Node> > NodeWriters; 464 NodeWriters node_writers; 465 466 typedef std::vector<std::pair<std::string, Edge> > EdgeWriters; 467 EdgeWriters edge_writers; 468 469 GUIWriter* gui_writer; 470 471 std::ostream& os; 472 const Graph& graph; 473 258 AttributeWriter<WriterTraits> attribute_writer; 474 259 }; 260 475 261 476 262 /// \brief Write a graph to the output. -
src/lemon/lemon_reader.h
r1408 r1409 31 31 32 32 #include <lemon/error.h> 33 #include "item_reader.h"33 #include <lemon/bits/item_reader.h> 34 34 35 35 36 36 namespace lemon { 37 37 38 /// \addtogroup io_group 39 /// @{ 40 38 /// \ingroup io_group 41 39 /// \brief Lemon Format reader class. 42 40 /// 41 /// The Lemon Format contains several sections. We do not want to 42 /// determine what sections are in a lemon file we give only a framework 43 /// to read a section oriented format. 44 /// 45 /// In the Lemon Format each section starts with a line contains a \c \@ 46 /// character on the first not white space position. This line is the 47 /// header line of the section. Each next lines belong to this section 48 /// while it does not starts with \c \@ character. This line can start a 49 /// new section or if it can close the file with the \c \@end line. 50 /// The file format ignore the empty lines and it may contain comments 51 /// started with a \c # character to the end of the line. 52 /// 53 /// The framework provides an abstract LemonReader::SectionReader class 54 /// what defines the interface of a SectionReader. The SectionReader 55 /// has the \c header() member function what get a header line string and 56 /// decides if it want to process the next section. Several SectionReaders 57 /// can be attached to an LemonReader and the first attached what can 58 /// process the section will be used. Its \c read() member will called 59 /// with a stream contains the section. From this stream the empty lines 60 /// and comments are filtered out. 61 /// 62 /// \relates GraphReader 63 /// \relates NodeSetReader 64 /// \relates EdgeSetReader 65 /// \relates NodesReader 66 /// \relates EdgesReader 67 /// \relates AttributeReader 43 68 class LemonReader { 44 69 private: … … 186 211 public: 187 212 213 /// \brief Abstract base class for reading a section. 214 /// 215 /// This class has an \c header() member function what get a 216 /// header line string and decides if it want to process the next 217 /// section. Several SectionReaders can be attached to an LemonReader 218 /// and the first attached what can process the section will be used. 219 /// Its \c read() member will called with a stream contains the section. 220 /// From this stream the empty lines and comments are filtered out. 188 221 class SectionReader { 189 public: 190 /// \e 222 friend class LemonReader; 223 protected: 224 /// \brief Constructor for SectionReader. 225 /// 226 /// Constructor for SectionReader. It attach this reader to 227 /// the given LemonReader. 228 SectionReader(LemonReader& reader) { 229 reader.attach(*this); 230 } 231 232 /// \brief Gives back true when the SectionReader can process 233 /// the section with the given header line. 234 /// 235 /// It gives back true when the SectionReader can process 236 /// the section with the given header line. 191 237 virtual bool header(const std::string& line) = 0; 192 /// \e 238 239 /// \brief Reader function of the section. 240 /// 241 /// It reads the content of the section. 193 242 virtual void read(std::istream& is) = 0; 194 243 }; 195 244 196 /// \e 245 /// \brief Constructor for LemonReader. 246 /// 247 /// Constructor for LemonReader which reads from the given stream. 197 248 LemonReader(std::istream& _is) 198 249 : is(&_is), own_is(false) {} 199 250 251 /// \brief Constructor for LemonReader. 252 /// 253 /// Constructor for LemonReader which reads from the given file. 200 254 LemonReader(const std::string& filename) 201 255 : is(0), own_is(true) { … … 203 257 } 204 258 205 259 /// \brief Desctructor for LemonReader. 260 /// 261 /// Desctructor for LemonReader. 206 262 ~LemonReader() { 207 263 if (own_is) { … … 214 270 void operator=(const LemonReader&); 215 271 216 public:217 218 /// \e219 272 void attach(SectionReader& reader) { 220 273 readers.push_back(&reader); 221 274 } 222 275 223 /// \e 224 void detach(SectionReader& reader) { 225 std::vector<SectionReader*>::iterator it = 226 std::find(readers.begin(), readers.end(), &reader); 227 if (it != readers.end()) { 228 readers.erase(it); 229 } 230 } 231 232 /// \e 276 public: 277 /// \brief Executes the LemonReader. 278 /// 279 /// It executes the LemonReader. 233 280 void run() { 234 281 int line_num = 0; … … 265 312 }; 266 313 267 268 /// \e 314 /// \brief Helper class for implementing the common SectionReaders. 315 /// 316 /// Helper class for implementing the common SectionReaders. 269 317 class CommonSectionReaderBase : public LemonReader::SectionReader { 318 typedef LemonReader::SectionReader Parent; 270 319 protected: 320 321 /// \brief Constructor for CommonSectionReaderBase. 322 /// 323 /// Constructor for CommonSectionReaderBase. It attach this reader to 324 /// the given LemonReader. 325 CommonSectionReaderBase(LemonReader& _reader) 326 : Parent(_reader) {} 327 271 328 template <typename _Item> 272 329 class ReaderBase; … … 434 491 435 492 template <typename _Item> 436 class ResolverReaderBase {493 class IdReaderBase { 437 494 public: 438 495 typedef _Item Item; 439 virtual Item re solve(std::istream& is) const = 0;496 virtual Item read(std::istream& is) const = 0; 440 497 }; 441 498 442 template <typename _Item, typename _ Resolver>443 class ResolverReader : public ResolverReaderBase<_Item> {499 template <typename _Item, typename _BoxedIdReader> 500 class IdReader : public IdReaderBase<_Item> { 444 501 public: 445 502 typedef _Item Item; 446 typedef _ Resolver Resolver;447 448 const Resolver& resolver;449 450 ResolverReader(const Resolver& _resolver)451 : resolver(_resolver) {}452 453 virtual Item re solve(std::istream& is) const {454 return resolver.resolve(is);503 typedef _BoxedIdReader BoxedIdReader; 504 505 const BoxedIdReader& boxedIdReader; 506 507 IdReader(const BoxedIdReader& _boxedIdReader) 508 : boxedIdReader(_boxedIdReader) {} 509 510 virtual Item read(std::istream& is) const { 511 return boxedIdReader.readId(is); 455 512 } 456 513 }; … … 480 537 }; 481 538 482 539 /// \ingroup io_group 540 /// \brief SectionReader for reading a graph's nodeset. 541 /// 542 /// The lemon format can store multiple graph nodesets with several maps. 543 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the 544 /// \c nodeset_id may be empty. 545 /// 546 /// The first line of the section contains the names of the maps separated 547 /// with white spaces. Each next lines describes a node in the nodeset, and 548 /// contains the mapped values for each map. 549 /// 550 /// If the nodeset contains an \c "id" named map then it will be regarded 551 /// as id map. This map should contain only unique values and when the 552 /// \c readId() member will read a value from the given stream it will 553 /// give back that node which is mapped to this value. 554 /// 555 /// \relates LemonReader 483 556 template <typename _Graph, typename _Traits = DefaultReaderTraits> 484 557 class NodeSetReader : public CommonSectionReaderBase { … … 491 564 typedef typename Traits::Skipper DefaultSkipper; 492 565 566 /// \brief Constructor. 567 /// 568 /// Constructor for NodeSetReader. It creates the NodeSetReader and 569 /// attach it into the given LemonReader. The nodeset reader will 570 /// add the readed nodes to the given Graph. The reader will read 571 /// the section when the \c section_id and the \c _id are the same. 493 572 NodeSetReader(LemonReader& _reader, Graph& _graph, 494 573 const std::string& _id = std::string(), 495 const DefaultSkipper& _defreader = DefaultSkipper()) 496 : graph(_graph), id(_id), skipper(_defreader) { 497 _reader.attach(*this); 498 } 499 574 const DefaultSkipper& _skipper = DefaultSkipper()) 575 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 576 577 578 /// \brief Destructor. 579 /// 580 /// Destructor for NodeSetReader. 500 581 virtual ~NodeSetReader() { 501 582 for (typename MapReaders::iterator it = readers.begin(); … … 551 632 } 552 633 553 /// \e 634 protected: 635 636 /// \brief Gives back true when the SectionReader can process 637 /// the section with the given header line. 638 /// 639 /// It gives back true when the header line starts with \c @nodeset, 640 /// and the header line's id and the nodeset's id are the same. 554 641 virtual bool header(const std::string& line) { 555 642 std::istringstream ls(line); … … 560 647 } 561 648 562 /// \e 649 /// \brief Reader function of the section. 650 /// 651 /// It reads the content of the section. 563 652 virtual void read(std::istream& is) { 564 653 std::vector<ReaderBase<Item>* > index; … … 588 677 } 589 678 590 bool isResolver() const { 679 public: 680 681 /// \brief Returns true if the nodeset can give back the node by its id. 682 /// 683 /// Returns true if the nodeset can give back the node by its id. 684 /// It is possible only if an "id" named map was read. 685 bool isIdReader() const { 591 686 return inverter.get() != 0; 592 687 } 593 688 594 typename Graph::Node resolve(std::istream& is) const { 689 /// \brief Gives back the node by its id. 690 /// 691 /// It reads an id from the stream and gives back which node belongs to 692 /// it. It is possible only if there was read an "id" named map. 693 typename Graph::Node readId(std::istream& is) const { 595 694 return inverter->read(is); 596 695 } … … 608 707 }; 609 708 610 611 612 /// \e 709 /// \ingroup io_group 710 /// \brief SectionReader for reading a graph's edgeset. 711 /// 712 /// The lemon format can store multiple graph edgesets with several maps. 713 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the 714 /// \c edgeset_id may be empty. 715 /// 716 /// The first line of the section contains the names of the maps separated 717 /// with white spaces. Each next lines describes a node in the nodeset. The 718 /// line contains the two nodes' id and the mapped values for each map. 719 /// 720 /// If the edgeset contains an \c "id" named map then it will be regarded 721 /// as id map. This map should contain only unique values and when the 722 /// \c readId() member will read a value from the given stream it will 723 /// give back that edge which is mapped to this value. 724 /// 725 /// The edgeset reader needs a node id reader to identify which nodes 726 /// have to be connected. If a NodeSetReader reads an "id" named map, 727 /// it will be able to resolve the nodes by ids. 728 /// 729 /// \relates LemonReader 613 730 template <typename _Graph, typename _Traits = DefaultReaderTraits> 614 731 class EdgeSetReader : public CommonSectionReaderBase { … … 621 738 typedef typename Traits::Skipper DefaultSkipper; 622 739 623 template <typename Resolver> 740 /// \brief Constructor. 741 /// 742 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and 743 /// attach it into the given LemonReader. The edgeset reader will 744 /// add the readed edges to the given Graph. It will use the given 745 /// node id reader to read the source and target nodes of the edges. 746 /// The reader will read the section only if the \c _id and the 747 /// \c edgset_id are the same. 748 template <typename NodeIdReader> 624 749 EdgeSetReader(LemonReader& _reader, Graph& _graph, 625 const Resolver& _nodeResolver,750 const NodeIdReader& _nodeIdReader, 626 751 const std::string& _id = std::string(), 627 const DefaultSkipper& _defreader = DefaultSkipper()) 628 : graph(_graph), id(_id), skipper(_defreader), 629 nodeResolver(new ResolverReader<typename Graph::Node, Resolver> 630 (_nodeResolver)) { 631 _reader.attach(*this); 632 } 633 752 const DefaultSkipper& _skipper = DefaultSkipper()) 753 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), 754 nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader> 755 (_nodeIdReader)) {} 756 757 /// \brief Destructor. 758 /// 759 /// Destructor for EdgeSetReader. 634 760 virtual ~EdgeSetReader() { 635 761 for (typename MapReaders::iterator it = readers.begin(); … … 645 771 public: 646 772 647 /// \brief Add a new node map reader command for the reader.648 /// 649 /// Add a new node map reader command for the reader.773 /// \brief Add a new edge map reader command for the reader. 774 /// 775 /// Add a new edge map reader command for the reader. 650 776 template <typename Map> 651 777 EdgeSetReader& readMap(std::string name, Map& map) { … … 654 780 } 655 781 656 /// \brief Add a new node map reader command for the reader.657 /// 658 /// Add a new node map reader command for the reader.782 /// \brief Add a new edge map reader command for the reader. 783 /// 784 /// Add a new edge map reader command for the reader. 659 785 template <typename Reader, typename Map> 660 786 EdgeSetReader& readMap(std::string name, Map& map, … … 670 796 } 671 797 672 /// \brief Add a new node map skipper command for the reader.673 /// 674 /// Add a new node map skipper command for the reader.798 /// \brief Add a new edge map skipper command for the reader. 799 /// 800 /// Add a new edge map skipper command for the reader. 675 801 template <typename Reader> 676 802 EdgeSetReader& skipMap(std::string name, … … 685 811 } 686 812 687 /// \e 813 protected: 814 815 /// \brief Gives back true when the SectionReader can process 816 /// the section with the given header line. 817 /// 818 /// It gives back true when the header line starts with \c @edgeset, 819 /// and the header line's id and the edgeset's id are the same. 688 820 virtual bool header(const std::string& line) { 689 821 std::istringstream ls(line); … … 694 826 } 695 827 696 /// \e 828 /// \brief Reader function of the section. 829 /// 830 /// It reads the content of the section. 697 831 virtual void read(std::istream& is) { 698 832 std::vector<ReaderBase<Item>* > index; … … 715 849 while (getline(is, line)) { 716 850 std::istringstream ls(line); 717 typename Graph::Node from = node Resolver->resolve(ls);718 typename Graph::Node to = node Resolver->resolve(ls);851 typename Graph::Node from = nodeIdReader->read(ls); 852 typename Graph::Node to = nodeIdReader->read(ls); 719 853 typename Graph::Edge edge = graph.addEdge(from, to); 720 854 for (int i = 0; i < (int)index.size(); ++i) { … … 724 858 } 725 859 726 bool isResolver() const { 860 public: 861 862 /// \brief Returns true if the edgeset can give back the edge by its id. 863 /// 864 /// Returns true if the edgeset can give back the edge by its id. 865 /// It is possible only if an "id" named map was read. 866 bool isIdReader() const { 727 867 return inverter.get() != 0; 728 868 } 729 869 730 typename Graph::Edge resolve(std::istream& is) { 870 /// \brief Gives back the edge by its id. 871 /// 872 /// It reads an id from the stream and gives back which edge belongs to 873 /// it. It is possible only if there was read an "id" named map. 874 typename Graph::Edge readId(std::istream& is) const { 731 875 return inverter->read(is); 732 876 } … … 742 886 743 887 std::auto_ptr<InverterBase<Item> > inverter; 744 std::auto_ptr< ResolverReaderBase<typename Graph::Node> > nodeResolver;888 std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader; 745 889 }; 746 890 747 748 /// \e 891 /// \ingroup io_group 892 /// \brief SectionReader for reading labeled nodes. 893 /// 894 /// The nodes section's header line is \c \@nodes \c nodes_id, but the 895 /// \c nodes_id may be empty. 896 /// 897 /// Each line in the section contains the name of the node 898 /// and then the node id. 899 /// 900 /// \relates LemonReader 901 template <typename _Graph> 902 class NodeReader : public CommonSectionReaderBase { 903 typedef CommonSectionReaderBase Parent; 904 typedef _Graph Graph; 905 typedef typename Graph::Node Item; 906 public: 907 908 /// \brief Constructor. 909 /// 910 /// Constructor for NodeReader. It creates the NodeReader and 911 /// attach it into the given LemonReader. It will use the given 912 /// node id reader to give back the nodes. The reader will read the 913 /// section only if the \c _id and the \c nodes_id are the same. 914 template <typename _IdReader> 915 NodeReader(LemonReader& _reader, const _IdReader& _idReader, 916 const std::string& _id = std::string()) 917 : Parent(_reader), id(_id), 918 idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 919 920 /// \brief Destructor. 921 /// 922 /// Destructor for NodeReader. 923 virtual ~NodeReader() {} 924 925 private: 926 NodeReader(const NodeReader&); 927 void operator=(const NodeReader&); 928 929 public: 930 931 /// \brief Add a node reader command for the NodeReader. 932 /// 933 /// Add a node reader command for the NodeReader. 934 void readNode(const std::string& name, Item& item) { 935 if (readers.find(name) != readers.end()) { 936 ErrorMessage msg; 937 msg << "Multiple read rule for node: " << name; 938 throw IOParameterError(msg.message()); 939 } 940 readers.insert(make_pair(name, &item)); 941 } 942 943 protected: 944 945 /// \brief Gives back true when the SectionReader can process 946 /// the section with the given header line. 947 /// 948 /// It gives back true when the header line start with \c @nodes, 949 /// and the header line's id and the reader's id are the same. 950 virtual bool header(const std::string& line) { 951 std::istringstream ls(line); 952 std::string command; 953 std::string name; 954 ls >> command >> name; 955 return command == "@nodes" && name == id; 956 } 957 958 /// \brief Reader function of the section. 959 /// 960 /// It reads the content of the section. 961 virtual void read(std::istream& is) { 962 std::string line; 963 while (getline(is, line)) { 964 std::istringstream ls(line); 965 std::string id; 966 ls >> id; 967 typename ItemReaders::iterator it = readers.find(id); 968 if (it != readers.end()) { 969 *(it->second) = idReader->read(ls); 970 } 971 } 972 } 973 974 private: 975 976 std::string id; 977 978 typedef std::map<std::string, Item*> ItemReaders; 979 ItemReaders readers; 980 std::auto_ptr<IdReaderBase<Item> > idReader; 981 }; 982 983 /// \ingroup io_group 984 /// \brief SectionReader for reading labeled edges. 985 /// 986 /// The edges section's header line is \c \@edges \c edges_id, but the 987 /// \c edges_id may be empty. 988 /// 989 /// Each line in the section contains the name of the edge 990 /// and then the edge id. 991 /// 992 /// \relates LemonReader 993 template <typename _Graph> 994 class EdgeReader : public CommonSectionReaderBase { 995 typedef CommonSectionReaderBase Parent; 996 typedef _Graph Graph; 997 typedef typename Graph::Edge Item; 998 public: 999 1000 /// \brief Constructor. 1001 /// 1002 /// Constructor for EdgeReader. It creates the EdgeReader and 1003 /// attach it into the given LemonReader. It will use the given 1004 /// edge id reader to give back the edges. The reader will read the 1005 /// section only if the \c _id and the \c nodes_id are the same. 1006 template <typename _IdReader> 1007 EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 1008 const std::string& _id = std::string()) 1009 : Parent(_reader), id(_id), 1010 idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 1011 1012 /// \brief Destructor. 1013 /// 1014 /// Destructor for EdgeReader. 1015 virtual ~EdgeReader() {} 1016 private: 1017 EdgeReader(const EdgeReader&); 1018 void operator=(const EdgeReader&); 1019 1020 public: 1021 1022 /// \brief Add an edge reader command for the EdgeReader. 1023 /// 1024 /// Add an edge reader command for the EdgeReader. 1025 void readEdge(const std::string& name, Item& item) { 1026 if (readers.find(name) != readers.end()) { 1027 ErrorMessage msg; 1028 msg << "Multiple read rule for edge: " << name; 1029 throw IOParameterError(msg.message()); 1030 } 1031 readers.insert(make_pair(name, &item)); 1032 } 1033 1034 protected: 1035 1036 /// \brief Gives back true when the SectionReader can process 1037 /// the section with the given header line. 1038 /// 1039 /// It gives back true when the header line start with \c @edges, 1040 /// and the header line's id and the reader's id are the same. 1041 virtual bool header(const std::string& line) { 1042 std::istringstream ls(line); 1043 std::string command; 1044 std::string name; 1045 ls >> command >> name; 1046 return command == "@edges" && name == id; 1047 } 1048 1049 /// \brief Reader function of the section. 1050 /// 1051 /// It reads the content of the section. 1052 virtual void read(std::istream& is) { 1053 std::string line; 1054 while (getline(is, line)) { 1055 std::istringstream ls(line); 1056 std::string id; 1057 ls >> id; 1058 typename ItemReaders::iterator it = readers.find(id); 1059 if (it != readers.end()) { 1060 *(it->second) = idReader->read(ls); 1061 } 1062 } 1063 } 1064 1065 private: 1066 1067 std::string id; 1068 1069 typedef std::map<std::string, Item*> ItemReaders; 1070 ItemReaders readers; 1071 std::auto_ptr<IdReaderBase<Item> > idReader; 1072 }; 1073 1074 /// \ingroup io_group 1075 /// \brief SectionReader for attributes. 1076 /// 1077 /// The lemon format can store multiple attribute set. Each set has 1078 /// the header line \c \@attributes \c attributeset_id, but the 1079 /// attributeset_id may be empty. 1080 /// 1081 /// The attributeset section contains several lines. Each of them starts 1082 /// with an attribute and then a the value for the id. 1083 /// 1084 /// \relates LemonReader 749 1085 template <typename _Traits = DefaultReaderTraits> 750 1086 class AttributeReader : public CommonSectionReaderBase { … … 752 1088 typedef _Traits Traits; 753 1089 public: 754 /// \e 1090 /// \brief Constructor. 1091 /// 1092 /// Constructor for AttributeReader. It creates the AttributeReader and 1093 /// attach it into the given LemonReader. The reader process a section 1094 /// only if the \c section_id and the \c _id are the same. 755 1095 AttributeReader(LemonReader& _reader, 756 const std::string& _id = std::string()) : id(_id) { 757 _reader.attach(*this); 758 } 759 760 /// \e 1096 const std::string& _id = std::string()) 1097 : Parent(_reader), id(_id) {} 1098 1099 /// \brief Destructor. 1100 /// 1101 /// Destructor for AttributeReader. 761 1102 virtual ~AttributeReader() { 762 1103 for (typename Readers::iterator it = readers.begin(); … … 771 1112 772 1113 public: 773 /// \e 1114 /// \brief Add an attribute reader command for the reader. 1115 /// 1116 /// Add an attribute reader command for the reader. 774 1117 template <typename Value> 775 1118 AttributeReader& readAttribute(const std::string& id, Value& value) { … … 778 1121 } 779 1122 780 /// \e 1123 /// \brief Add an attribute reader command for the reader. 1124 /// 1125 /// Add an attribute reader command for the reader. 781 1126 template <typename Reader, typename Value> 782 1127 AttributeReader& readAttribute(const std::string& name, Value& value, … … 792 1137 } 793 1138 794 /// \e 1139 protected: 1140 1141 /// \brief Gives back true when the SectionReader can process 1142 /// the section with the given header line. 1143 /// 1144 /// It gives back true when the header line start with \c @attributes, 1145 /// and the header line's id and the attributeset's id are the same. 795 1146 bool header(const std::string& line) { 796 1147 std::istringstream ls(line); … … 801 1152 } 802 1153 803 /// \e 1154 /// \brief Reader function of the section. 1155 /// 1156 /// It reads the content of the section. 804 1157 void read(std::istream& is) { 805 1158 std::string line; … … 819 1172 820 1173 typedef std::map<std::string, ValueReaderBase*> Readers; 821 Readers readers; 822 1174 Readers readers; 823 1175 }; 824 1176 825 template <typename _Graph> 826 class NodeReader : public CommonSectionReaderBase { 827 typedef CommonSectionReaderBase Parent; 828 typedef _Graph Graph; 829 typedef typename Graph::Node Item; 830 public: 831 832 template <typename Resolver> 833 NodeReader(LemonReader& _reader, const Resolver& _resolver, 834 const std::string& _id = std::string()) 835 : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver> 836 (_resolver)) { 837 _reader.attach(*this); 838 } 839 840 virtual ~NodeReader() {} 841 842 private: 843 NodeReader(const NodeReader&); 844 void operator=(const NodeReader&); 845 846 public: 847 848 void readNode(const std::string& name, Item& item) { 849 if (readers.find(name) != readers.end()) { 850 ErrorMessage msg; 851 msg << "Multiple read rule for node: " << name; 852 throw IOParameterError(msg.message()); 853 } 854 readers.insert(make_pair(name, &item)); 855 } 856 857 virtual bool header(const std::string& line) { 858 std::istringstream ls(line); 859 std::string command; 860 std::string name; 861 ls >> command >> name; 862 return command == "@nodes" && name == id; 863 } 864 865 virtual void read(std::istream& is) { 866 std::string line; 867 while (getline(is, line)) { 868 std::istringstream ls(line); 869 std::string id; 870 ls >> id; 871 typename ItemReaders::iterator it = readers.find(id); 872 if (it != readers.end()) { 873 *(it->second) = resolver->resolve(ls); 874 } 875 } 876 } 877 878 private: 879 880 std::string id; 881 882 typedef std::map<std::string, Item*> ItemReaders; 883 ItemReaders readers; 884 std::auto_ptr<ResolverReaderBase<Item> > resolver; 885 }; 886 887 template <typename _Graph> 888 class EdgeReader : public CommonSectionReaderBase { 889 typedef CommonSectionReaderBase Parent; 890 typedef _Graph Graph; 891 typedef typename Graph::Edge Item; 892 public: 893 894 template <typename Resolver> 895 EdgeReader(LemonReader& _reader, const Resolver& _resolver, 896 const std::string& _id = std::string()) 897 : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver> 898 (_resolver)) { 899 _reader.attach(*this); 900 } 901 902 virtual ~EdgeReader() {} 903 private: 904 EdgeReader(const EdgeReader&); 905 void operator=(const EdgeReader&); 906 907 public: 908 909 void readEdge(const std::string& name, Item& item) { 910 if (readers.find(name) != readers.end()) { 911 ErrorMessage msg; 912 msg << "Multiple read rule for edge: " << name; 913 throw IOParameterError(msg.message()); 914 } 915 readers.insert(make_pair(name, &item)); 916 } 917 918 919 virtual bool header(const std::string& line) { 920 std::istringstream ls(line); 921 std::string command; 922 std::string name; 923 ls >> command >> name; 924 return command == "@nodes" && name == id; 925 } 926 927 virtual void read(std::istream& is) { 928 std::string line; 929 while (getline(is, line)) { 930 std::istringstream ls(line); 931 std::string id; 932 ls >> id; 933 typename ItemReaders::iterator it = readers.find(id); 934 if (it != readers.end()) { 935 *(it->second) = resolver->resolve(ls); 936 } 937 } 938 } 939 940 private: 941 942 std::string id; 943 944 typedef std::map<std::string, Item*> ItemReaders; 945 ItemReaders readers; 946 std::auto_ptr<ResolverReaderBase<Item> > resolver; 947 }; 948 949 /// \e 950 class PrintReader : public LemonReader::SectionReader { 951 typedef LemonReader::SectionReader Parent; 952 public: 953 954 /// \e 955 PrintReader(LemonReader& reader) { 956 reader.attach(*this); 957 } 958 959 /// \e 960 bool header(const std::string& line) { 961 std::cout << "Asked header: " << line << std::endl; 962 return true; 963 } 964 965 /// \e 966 void read(std::istream& is) { 967 std::string line; 968 while (std::getline(is, line)) { 969 std::cout << line << std::endl; 970 } 971 } 972 973 }; 974 975 /// @} 1177 976 1178 } 977 1179 #endif
Note: See TracChangeset
for help on using the changeset viewer.