1 /* -*- C++ -*- |
|
2 * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library |
|
3 * |
|
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
5 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
6 * |
|
7 * Permission to use, modify and distribute this software is granted |
|
8 * provided that this copyright notice appears in all copies. For |
|
9 * precise terms see the accompanying LICENSE file. |
|
10 * |
|
11 * This software is provided "AS IS" with no warranty of any kind, |
|
12 * express or implied, and with no claim as to its suitability for any |
|
13 * purpose. |
|
14 * |
|
15 */ |
|
16 |
|
17 ///\ingroup io_group |
|
18 ///\file |
|
19 ///\brief Lemon Format reader. |
|
20 |
|
21 |
|
22 #ifndef LEMON_LEMON_READER_H |
|
23 #define LEMON_LEMON_READER_H |
|
24 |
|
25 |
|
26 #include <iostream> |
|
27 #include <fstream> |
|
28 #include <string> |
|
29 #include <vector> |
|
30 #include <algorithm> |
|
31 #include <map> |
|
32 #include <memory> |
|
33 |
|
34 #include <lemon/error.h> |
|
35 #include <lemon/graph_utils.h> |
|
36 #include <lemon/utility.h> |
|
37 #include <lemon/bits/item_reader.h> |
|
38 |
|
39 |
|
40 namespace lemon { |
|
41 |
|
42 namespace _reader_bits { |
|
43 |
|
44 template <typename T> |
|
45 bool operator<(T, T) { |
|
46 throw DataFormatError("Id is not comparable"); |
|
47 } |
|
48 |
|
49 template <typename T> |
|
50 struct Less { |
|
51 bool operator()(const T& p, const T& q) const { |
|
52 return p < q; |
|
53 } |
|
54 }; |
|
55 |
|
56 template <typename M1, typename M2> |
|
57 class WriteComposeMap { |
|
58 public: |
|
59 typedef True NeedCopy; |
|
60 |
|
61 typedef typename M2::Key Key; |
|
62 typedef typename M1::Value Value; |
|
63 |
|
64 WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2) |
|
65 : m1(_m1), m2(_m2) {} |
|
66 |
|
67 void set(const Key& key, const Value& value) { |
|
68 m1.set(m2[key], value); |
|
69 } |
|
70 |
|
71 private: |
|
72 |
|
73 typename SmartReference<M1>::Type m1; |
|
74 typename SmartConstReference<M2>::Type m2; |
|
75 |
|
76 }; |
|
77 |
|
78 template <typename M1, typename M2> |
|
79 WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) { |
|
80 return WriteComposeMap<M1, M2>(m1, m2); |
|
81 } |
|
82 |
|
83 template <typename M1, typename M2> |
|
84 WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) { |
|
85 return WriteComposeMap<M1, M2>(m1, m2); |
|
86 } |
|
87 |
|
88 } |
|
89 |
|
90 /// \ingroup io_group |
|
91 /// \brief Lemon Format reader class. |
|
92 /// |
|
93 /// The Lemon Format contains several sections. We do not want to |
|
94 /// determine what sections are in a lemon file we give only a framework |
|
95 /// to read a section oriented format. |
|
96 /// |
|
97 /// In the Lemon Format each section starts with a line contains a \c \@ |
|
98 /// character on the first not white space position. This line is the |
|
99 /// header line of the section. Each next lines belong to this section |
|
100 /// while it does not starts with \c \@ character. This line can start a |
|
101 /// new section or if it can close the file with the \c \@end line. |
|
102 /// The file format ignore the empty and comment lines. The line is |
|
103 /// comment line if it starts with a \c # character. |
|
104 /// |
|
105 /// The framework provides an abstract LemonReader::SectionReader class |
|
106 /// what defines the interface of a SectionReader. The SectionReader |
|
107 /// has the \c header() member function what get a header line string and |
|
108 /// decides if it want to process the next section. Several SectionReaders |
|
109 /// can be attached to an LemonReader and the first attached what can |
|
110 /// process the section will be used. Its \c read() member will called |
|
111 /// with a stream contains the section. From this stream the empty and |
|
112 /// comment lines are filtered out. |
|
113 /// |
|
114 /// \relates GraphReader |
|
115 /// \relates NodeSetReader |
|
116 /// \relates EdgeSetReader |
|
117 /// \relates NodesReader |
|
118 /// \relates EdgesReader |
|
119 /// \relates AttributeReader |
|
120 class LemonReader { |
|
121 private: |
|
122 |
|
123 class FilterStreamBuf : public std::streambuf { |
|
124 public: |
|
125 |
|
126 typedef std::streambuf Parent; |
|
127 typedef Parent::char_type char_type; |
|
128 FilterStreamBuf(std::istream& is, int& num) |
|
129 : _is(is), _base(0), _eptr(0), |
|
130 _num(num), skip_state(after_endl) {} |
|
131 |
|
132 protected: |
|
133 |
|
134 enum skip_state_type { |
|
135 no_skip, |
|
136 after_endl, |
|
137 comment_line |
|
138 }; |
|
139 |
|
140 char_type small_buf[1]; |
|
141 |
|
142 |
|
143 std::istream& _is; |
|
144 |
|
145 char_type* _base; |
|
146 char_type* _eptr; |
|
147 |
|
148 int& _num; |
|
149 |
|
150 skip_state_type skip_state; |
|
151 |
|
152 |
|
153 char_type* base() { return _base; } |
|
154 |
|
155 char_type* eptr() { return _eptr; } |
|
156 |
|
157 int blen() { return _eptr - _base; } |
|
158 |
|
159 void setb(char_type* buf, int len) { |
|
160 _base = buf; |
|
161 _eptr = buf + len; |
|
162 } |
|
163 |
|
164 virtual std::streambuf* setbuf(char *buf, int len) { |
|
165 if (base()) return 0; |
|
166 if (buf != 0 && len >= (int)sizeof(small_buf)) { |
|
167 setb(buf, len); |
|
168 } else { |
|
169 setb(small_buf, sizeof(small_buf)); |
|
170 } |
|
171 setg(0, 0, 0); |
|
172 return this; |
|
173 } |
|
174 |
|
175 bool put_char(char c) { |
|
176 switch (skip_state) { |
|
177 case no_skip: |
|
178 switch (c) { |
|
179 case '\n': |
|
180 skip_state = after_endl; |
|
181 return true; |
|
182 default: |
|
183 return true; |
|
184 } |
|
185 case after_endl: |
|
186 switch (c) { |
|
187 case '@': |
|
188 return false; |
|
189 case '\n': |
|
190 return false; |
|
191 case '#': |
|
192 skip_state = comment_line; |
|
193 return false; |
|
194 default: |
|
195 if (!isspace(c)) { |
|
196 skip_state = no_skip; |
|
197 return true; |
|
198 } else { |
|
199 return false; |
|
200 } |
|
201 } |
|
202 break; |
|
203 case comment_line: |
|
204 switch (c) { |
|
205 case '\n': |
|
206 skip_state = after_endl; |
|
207 return false; |
|
208 default: |
|
209 return false; |
|
210 } |
|
211 } |
|
212 return false; |
|
213 } |
|
214 |
|
215 virtual int underflow() { |
|
216 char c; |
|
217 if (_is.read(&c, 1)) { |
|
218 _is.putback(c); |
|
219 if (c == '@') { |
|
220 return EOF; |
|
221 } |
|
222 } else { |
|
223 return EOF; |
|
224 } |
|
225 char_type *ptr; |
|
226 for (ptr = base(); ptr != eptr(); ++ptr) { |
|
227 if (_is.read(&c, 1)) { |
|
228 if (c == '\n') ++_num; |
|
229 if (put_char(c)) { |
|
230 *ptr = c; |
|
231 } else { |
|
232 if (skip_state == after_endl && c == '@') { |
|
233 _is.putback('@'); |
|
234 break; |
|
235 } |
|
236 --ptr; |
|
237 } |
|
238 } else { |
|
239 break; |
|
240 } |
|
241 } |
|
242 setg(base(), base(), ptr); |
|
243 return *base(); |
|
244 } |
|
245 |
|
246 virtual int sync() { |
|
247 return EOF; |
|
248 } |
|
249 }; |
|
250 |
|
251 public: |
|
252 |
|
253 /// \brief Abstract base class for reading a section. |
|
254 /// |
|
255 /// This class has an \c header() member function what get a |
|
256 /// header line string and decides if it want to process the next |
|
257 /// section. Several SectionReaders can be attached to an LemonReader |
|
258 /// and the first attached what can process the section will be used. |
|
259 /// Its \c read() member will called with a stream contains the section. |
|
260 /// From this stream the empty lines and comments are filtered out. |
|
261 class SectionReader { |
|
262 friend class LemonReader; |
|
263 protected: |
|
264 /// \brief Constructor for SectionReader. |
|
265 /// |
|
266 /// Constructor for SectionReader. It attach this reader to |
|
267 /// the given LemonReader. |
|
268 SectionReader(LemonReader& reader) { |
|
269 reader.attach(*this); |
|
270 } |
|
271 |
|
272 /// \brief Gives back true when the SectionReader can process |
|
273 /// the section with the given header line. |
|
274 /// |
|
275 /// It gives back true when the SectionReader can process |
|
276 /// the section with the given header line. |
|
277 virtual bool header(const std::string& line) = 0; |
|
278 |
|
279 /// \brief Reader function of the section. |
|
280 /// |
|
281 /// It reads the content of the section. |
|
282 virtual void read(std::istream& is) = 0; |
|
283 }; |
|
284 |
|
285 /// \brief Constructor for LemonReader. |
|
286 /// |
|
287 /// Constructor for LemonReader which reads from the given stream. |
|
288 LemonReader(std::istream& _is) |
|
289 : is(&_is), own_is(false) {} |
|
290 |
|
291 /// \brief Constructor for LemonReader. |
|
292 /// |
|
293 /// Constructor for LemonReader which reads from the given file. |
|
294 LemonReader(const std::string& filename) |
|
295 : is(0), own_is(true) { |
|
296 is = new std::ifstream(filename.c_str()); |
|
297 } |
|
298 |
|
299 /// \brief Desctructor for LemonReader. |
|
300 /// |
|
301 /// Desctructor for LemonReader. |
|
302 ~LemonReader() { |
|
303 if (own_is) { |
|
304 delete is; |
|
305 } |
|
306 } |
|
307 |
|
308 private: |
|
309 LemonReader(const LemonReader&); |
|
310 void operator=(const LemonReader&); |
|
311 |
|
312 void attach(SectionReader& reader) { |
|
313 readers.push_back(&reader); |
|
314 } |
|
315 |
|
316 public: |
|
317 /// \brief Executes the LemonReader. |
|
318 /// |
|
319 /// It executes the LemonReader. |
|
320 void run() { |
|
321 int line_num = 0; |
|
322 std::string line; |
|
323 try { |
|
324 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) { |
|
325 SectionReaders::iterator it; |
|
326 for (it = readers.begin(); it != readers.end(); ++it) { |
|
327 if ((*it)->header(line)) { |
|
328 char buf[2048]; |
|
329 FilterStreamBuf buffer(*is, line_num); |
|
330 buffer.pubsetbuf(buf, sizeof(buf)); |
|
331 std::istream is(&buffer); |
|
332 (*it)->read(is); |
|
333 break; |
|
334 } |
|
335 } |
|
336 } |
|
337 } catch (DataFormatError& error) { |
|
338 error.line(line_num); |
|
339 throw error; |
|
340 } |
|
341 } |
|
342 |
|
343 |
|
344 private: |
|
345 |
|
346 std::istream* is; |
|
347 bool own_is; |
|
348 |
|
349 typedef std::vector<SectionReader*> SectionReaders; |
|
350 SectionReaders readers; |
|
351 |
|
352 }; |
|
353 |
|
354 /// \brief Helper class for implementing the common SectionReaders. |
|
355 /// |
|
356 /// Helper class for implementing the common SectionReaders. |
|
357 class CommonSectionReaderBase : public LemonReader::SectionReader { |
|
358 typedef LemonReader::SectionReader Parent; |
|
359 protected: |
|
360 |
|
361 /// \brief Constructor for CommonSectionReaderBase. |
|
362 /// |
|
363 /// Constructor for CommonSectionReaderBase. It attach this reader to |
|
364 /// the given LemonReader. |
|
365 CommonSectionReaderBase(LemonReader& _reader) |
|
366 : Parent(_reader) {} |
|
367 |
|
368 template <typename _Item> |
|
369 class ReaderBase; |
|
370 |
|
371 template <typename _Item> |
|
372 class InverterBase : public ReaderBase<_Item> { |
|
373 public: |
|
374 typedef _Item Item; |
|
375 virtual void read(std::istream&, const Item&) = 0; |
|
376 virtual Item read(std::istream&) const = 0; |
|
377 |
|
378 virtual InverterBase<_Item>* getInverter() { |
|
379 return this; |
|
380 } |
|
381 }; |
|
382 |
|
383 template <typename _Item, typename _Map, typename _Reader> |
|
384 class MapReaderInverter : public InverterBase<_Item> { |
|
385 public: |
|
386 typedef _Item Item; |
|
387 typedef _Reader Reader; |
|
388 typedef typename Reader::Value Value; |
|
389 typedef _Map Map; |
|
390 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse; |
|
391 |
|
392 typename SmartReference<Map>::Type map; |
|
393 Reader reader; |
|
394 Inverse inverse; |
|
395 |
|
396 MapReaderInverter(typename SmartParameter<Map>::Type _map, |
|
397 const Reader& _reader) |
|
398 : map(_map), reader(_reader) {} |
|
399 |
|
400 virtual ~MapReaderInverter() {} |
|
401 |
|
402 virtual void read(std::istream& is, const Item& item) { |
|
403 Value value; |
|
404 reader.read(is, value); |
|
405 map.set(item, value); |
|
406 typename Inverse::iterator it = inverse.find(value); |
|
407 if (it == inverse.end()) { |
|
408 inverse.insert(std::make_pair(value, item)); |
|
409 } else { |
|
410 throw DataFormatError("Multiple ID occurence"); |
|
411 } |
|
412 } |
|
413 |
|
414 virtual Item read(std::istream& is) const { |
|
415 Value value; |
|
416 reader.read(is, value); |
|
417 typename Inverse::const_iterator it = inverse.find(value); |
|
418 if (it != inverse.end()) { |
|
419 return it->second; |
|
420 } else { |
|
421 throw DataFormatError("Invalid ID error"); |
|
422 } |
|
423 } |
|
424 }; |
|
425 |
|
426 template <typename _Item, typename _Reader> |
|
427 class SkipReaderInverter : public InverterBase<_Item> { |
|
428 public: |
|
429 typedef _Item Item; |
|
430 typedef _Reader Reader; |
|
431 typedef typename Reader::Value Value; |
|
432 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse; |
|
433 |
|
434 Reader reader; |
|
435 |
|
436 SkipReaderInverter(const Reader& _reader) |
|
437 : reader(_reader) {} |
|
438 |
|
439 virtual ~SkipReaderInverter() {} |
|
440 |
|
441 virtual void read(std::istream& is, const Item& item) { |
|
442 Value value; |
|
443 reader.read(is, value); |
|
444 typename Inverse::iterator it = inverse.find(value); |
|
445 if (it == inverse.end()) { |
|
446 inverse.insert(std::make_pair(value, item)); |
|
447 } else { |
|
448 throw DataFormatError("Multiple ID occurence error"); |
|
449 } |
|
450 } |
|
451 |
|
452 virtual Item read(std::istream& is) const { |
|
453 Value value; |
|
454 reader.read(is, value); |
|
455 typename Inverse::const_iterator it = inverse.find(value); |
|
456 if (it != inverse.end()) { |
|
457 return it->second; |
|
458 } else { |
|
459 throw DataFormatError("Invalid ID error"); |
|
460 } |
|
461 } |
|
462 |
|
463 private: |
|
464 Inverse inverse; |
|
465 }; |
|
466 |
|
467 template <typename _Item> |
|
468 class ReaderBase { |
|
469 public: |
|
470 typedef _Item Item; |
|
471 |
|
472 virtual ~ReaderBase() {} |
|
473 |
|
474 virtual void read(std::istream& is, const Item& item) = 0; |
|
475 virtual InverterBase<_Item>* getInverter() = 0; |
|
476 }; |
|
477 |
|
478 template <typename _Item, typename _Map, typename _Reader> |
|
479 class MapReader : public ReaderBase<_Item> { |
|
480 public: |
|
481 typedef _Map Map; |
|
482 typedef _Reader Reader; |
|
483 typedef typename Reader::Value Value; |
|
484 typedef _Item Item; |
|
485 |
|
486 typename SmartReference<Map>::Type map; |
|
487 Reader reader; |
|
488 |
|
489 MapReader(typename SmartParameter<Map>::Type _map, |
|
490 const Reader& _reader) |
|
491 : map(_map), reader(_reader) {} |
|
492 |
|
493 virtual ~MapReader() {} |
|
494 |
|
495 virtual void read(std::istream& is, const Item& item) { |
|
496 Value value; |
|
497 reader.read(is, value); |
|
498 map.set(item, value); |
|
499 } |
|
500 |
|
501 virtual InverterBase<_Item>* getInverter() { |
|
502 return new MapReaderInverter<Item, Map, Reader>(map, reader); |
|
503 } |
|
504 }; |
|
505 |
|
506 |
|
507 template <typename _Item, typename _Reader> |
|
508 class SkipReader : public ReaderBase<_Item> { |
|
509 public: |
|
510 typedef _Reader Reader; |
|
511 typedef typename Reader::Value Value; |
|
512 typedef _Item Item; |
|
513 |
|
514 Reader reader; |
|
515 SkipReader(const Reader& _reader) : reader(_reader) {} |
|
516 |
|
517 virtual ~SkipReader() {} |
|
518 |
|
519 virtual void read(std::istream& is, const Item&) { |
|
520 Value value; |
|
521 reader.read(is, value); |
|
522 } |
|
523 |
|
524 virtual InverterBase<Item>* getInverter() { |
|
525 return new SkipReaderInverter<Item, Reader>(reader); |
|
526 } |
|
527 }; |
|
528 |
|
529 template <typename _Item> |
|
530 class IdReaderBase { |
|
531 public: |
|
532 typedef _Item Item; |
|
533 virtual Item read(std::istream& is) const = 0; |
|
534 }; |
|
535 |
|
536 template <typename _Item, typename _BoxedIdReader> |
|
537 class IdReader : public IdReaderBase<_Item> { |
|
538 public: |
|
539 typedef _Item Item; |
|
540 typedef _BoxedIdReader BoxedIdReader; |
|
541 |
|
542 const BoxedIdReader& boxedIdReader; |
|
543 |
|
544 IdReader(const BoxedIdReader& _boxedIdReader) |
|
545 : boxedIdReader(_boxedIdReader) {} |
|
546 |
|
547 virtual Item read(std::istream& is) const { |
|
548 return boxedIdReader.readId(is, Item()); |
|
549 } |
|
550 }; |
|
551 |
|
552 class ValueReaderBase { |
|
553 public: |
|
554 virtual void read(std::istream&) {}; |
|
555 }; |
|
556 |
|
557 template <typename _Value, typename _Reader> |
|
558 class ValueReader : public ValueReaderBase { |
|
559 public: |
|
560 typedef _Value Value; |
|
561 typedef _Reader Reader; |
|
562 |
|
563 ValueReader(Value& _value, const Reader& _reader) |
|
564 : value(_value), reader(_reader) {} |
|
565 |
|
566 virtual void read(std::istream& is) { |
|
567 reader.read(is, value); |
|
568 } |
|
569 private: |
|
570 Value& value; |
|
571 Reader reader; |
|
572 }; |
|
573 |
|
574 }; |
|
575 |
|
576 /// \ingroup io_group |
|
577 /// \brief SectionReader for reading a graph's nodeset. |
|
578 /// |
|
579 /// The lemon format can store multiple graph nodesets with several maps. |
|
580 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the |
|
581 /// \c nodeset_id may be empty. |
|
582 /// |
|
583 /// The first line of the section contains the names of the maps separated |
|
584 /// with white spaces. Each next lines describes a node in the nodeset, and |
|
585 /// contains the mapped values for each map. |
|
586 /// |
|
587 /// If the nodeset contains an \c "id" named map then it will be regarded |
|
588 /// as id map. This map should contain only unique values and when the |
|
589 /// \c readId() member will read a value from the given stream it will |
|
590 /// give back that node which is mapped to this value. |
|
591 /// |
|
592 /// \relates LemonReader |
|
593 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
|
594 class NodeSetReader : public CommonSectionReaderBase { |
|
595 typedef CommonSectionReaderBase Parent; |
|
596 public: |
|
597 |
|
598 typedef _Graph Graph; |
|
599 typedef _Traits Traits; |
|
600 typedef typename Graph::Node Node; |
|
601 typedef typename Traits::Skipper DefaultSkipper; |
|
602 |
|
603 /// \brief Constructor. |
|
604 /// |
|
605 /// Constructor for NodeSetReader. It creates the NodeSetReader and |
|
606 /// attach it into the given LemonReader. The nodeset reader will |
|
607 /// add the readed nodes to the given Graph. The reader will read |
|
608 /// the section when the \c section_id and the \c _id are the same. |
|
609 NodeSetReader(LemonReader& _reader, |
|
610 typename SmartParameter<Graph>::Type _graph, |
|
611 const std::string& _id = std::string(), |
|
612 const DefaultSkipper& _skipper = DefaultSkipper()) |
|
613 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} |
|
614 |
|
615 |
|
616 /// \brief Destructor. |
|
617 /// |
|
618 /// Destructor for NodeSetReader. |
|
619 virtual ~NodeSetReader() { |
|
620 for (typename MapReaders::iterator it = readers.begin(); |
|
621 it != readers.end(); ++it) { |
|
622 delete it->second; |
|
623 } |
|
624 } |
|
625 |
|
626 private: |
|
627 NodeSetReader(const NodeSetReader&); |
|
628 void operator=(const NodeSetReader&); |
|
629 |
|
630 public: |
|
631 |
|
632 /// \brief Add a new node map reader command for the reader. |
|
633 /// |
|
634 /// Add a new node map reader command for the reader. |
|
635 template <typename Map> |
|
636 NodeSetReader& readNodeMap(std::string name, Map& map) { |
|
637 return _readMap< |
|
638 typename Traits::template Reader<typename Map::Value>, Map, |
|
639 typename SmartParameter<Map>::Type>(name, map); |
|
640 } |
|
641 |
|
642 template <typename Map> |
|
643 NodeSetReader& readNodeMap(std::string name, const Map& map) { |
|
644 return _readMap< |
|
645 typename Traits::template Reader<typename Map::Value>, Map, |
|
646 typename SmartParameter<Map>::Type>(name, map); |
|
647 } |
|
648 |
|
649 /// \brief Add a new node map reader command for the reader. |
|
650 /// |
|
651 /// Add a new node map reader command for the reader. |
|
652 template <typename Reader, typename Map> |
|
653 NodeSetReader& readNodeMap(std::string name, Map& map, |
|
654 const Reader& reader = Reader()) { |
|
655 return _readMap<Reader, Map, typename SmartParameter<Map>::Type> |
|
656 (name, map, reader); |
|
657 } |
|
658 |
|
659 template <typename Reader, typename Map> |
|
660 NodeSetReader& readNodeMap(std::string name, const Map& map, |
|
661 const Reader& reader = Reader()) { |
|
662 return _readMap<Reader, Map, typename SmartParameter<Map>::Type> |
|
663 (name, map, reader); |
|
664 } |
|
665 |
|
666 private: |
|
667 |
|
668 template <typename Reader, typename Map, typename MapParameter> |
|
669 NodeSetReader& _readMap(std::string name, MapParameter map, |
|
670 const Reader& reader = Reader()) { |
|
671 if (readers.find(name) != readers.end()) { |
|
672 ErrorMessage msg; |
|
673 msg << "Multiple read rule for node map: " << name; |
|
674 throw IOParameterError(msg.message()); |
|
675 } |
|
676 readers.insert( |
|
677 make_pair(name, new MapReader<Node, Map, Reader>(map, reader))); |
|
678 return *this; |
|
679 } |
|
680 |
|
681 public: |
|
682 |
|
683 /// \brief Add a new node map skipper command for the reader. |
|
684 /// |
|
685 /// Add a new node map skipper command for the reader. |
|
686 template <typename Reader> |
|
687 NodeSetReader& skipNodeMap(std::string name, |
|
688 const Reader& reader = Reader()) { |
|
689 if (readers.find(name) != readers.end()) { |
|
690 ErrorMessage msg; |
|
691 msg << "Multiple read rule for node map: " << name; |
|
692 throw IOParameterError(msg.message()); |
|
693 } |
|
694 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader))); |
|
695 return *this; |
|
696 } |
|
697 |
|
698 protected: |
|
699 |
|
700 /// \brief Gives back true when the SectionReader can process |
|
701 /// the section with the given header line. |
|
702 /// |
|
703 /// It gives back true when the header line starts with \c \@nodeset, |
|
704 /// and the header line's id and the nodeset's id are the same. |
|
705 virtual bool header(const std::string& line) { |
|
706 std::istringstream ls(line); |
|
707 std::string command; |
|
708 std::string name; |
|
709 ls >> command >> name; |
|
710 return command == "@nodeset" && name == id; |
|
711 } |
|
712 |
|
713 /// \brief Reader function of the section. |
|
714 /// |
|
715 /// It reads the content of the section. |
|
716 virtual void read(std::istream& is) { |
|
717 std::vector<ReaderBase<Node>* > index; |
|
718 std::string line; |
|
719 |
|
720 getline(is, line); |
|
721 std::istringstream ls(line); |
|
722 while (ls >> id) { |
|
723 typename MapReaders::iterator it = readers.find(id); |
|
724 if (it != readers.end()) { |
|
725 index.push_back(it->second); |
|
726 } else { |
|
727 index.push_back(&skipper); |
|
728 } |
|
729 if (id == "id" && inverter.get() == 0) { |
|
730 inverter.reset(index.back()->getInverter()); |
|
731 index.back() = inverter.get(); |
|
732 } |
|
733 } |
|
734 while (getline(is, line)) { |
|
735 Node node = graph.addNode(); |
|
736 std::istringstream ls(line); |
|
737 for (int i = 0; i < (int)index.size(); ++i) { |
|
738 index[i]->read(ls, node); |
|
739 } |
|
740 } |
|
741 } |
|
742 |
|
743 public: |
|
744 |
|
745 /// \brief Returns true if the nodeset can give back the node by its id. |
|
746 /// |
|
747 /// Returns true if the nodeset can give back the node by its id. |
|
748 /// It is possible only if an "id" named map was read. |
|
749 bool isIdReader() const { |
|
750 return inverter.get() != 0; |
|
751 } |
|
752 |
|
753 /// \brief Gives back the node by its id. |
|
754 /// |
|
755 /// It reads an id from the stream and gives back which node belongs to |
|
756 /// it. It is possible only if there was read an "id" named map. |
|
757 Node readId(std::istream& is, Node = Node()) const { |
|
758 return inverter->read(is); |
|
759 } |
|
760 |
|
761 private: |
|
762 |
|
763 typedef std::map<std::string, ReaderBase<Node>*> MapReaders; |
|
764 MapReaders readers; |
|
765 |
|
766 typename SmartReference<Graph>::Type graph; |
|
767 std::string id; |
|
768 SkipReader<Node, DefaultSkipper> skipper; |
|
769 |
|
770 std::auto_ptr<InverterBase<Node> > inverter; |
|
771 }; |
|
772 |
|
773 /// \ingroup io_group |
|
774 /// \brief SectionReader for reading a graph's edgeset. |
|
775 /// |
|
776 /// The lemon format can store multiple graph edgesets with several maps. |
|
777 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the |
|
778 /// \c edgeset_id may be empty. |
|
779 /// |
|
780 /// The first line of the section contains the names of the maps separated |
|
781 /// with white spaces. Each next lines describes an edge in the edgeset. The |
|
782 /// line contains the source and the target nodes' id and the mapped |
|
783 /// values for each map. |
|
784 /// |
|
785 /// If the edgeset contains an \c "id" named map then it will be regarded |
|
786 /// as id map. This map should contain only unique values and when the |
|
787 /// \c readId() member will read a value from the given stream it will |
|
788 /// give back that edge which is mapped to this value. |
|
789 /// |
|
790 /// The edgeset reader needs a node id reader to identify which nodes |
|
791 /// have to be connected. If a NodeSetReader reads an "id" named map, |
|
792 /// it will be able to resolve the nodes by ids. |
|
793 /// |
|
794 /// \relates LemonReader |
|
795 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
|
796 class EdgeSetReader : public CommonSectionReaderBase { |
|
797 typedef CommonSectionReaderBase Parent; |
|
798 public: |
|
799 |
|
800 typedef _Graph Graph; |
|
801 typedef _Traits Traits; |
|
802 typedef typename Graph::Node Node; |
|
803 typedef typename Graph::Edge Edge; |
|
804 typedef typename Traits::Skipper DefaultSkipper; |
|
805 |
|
806 /// \brief Constructor. |
|
807 /// |
|
808 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and |
|
809 /// attach it into the given LemonReader. The edgeset reader will |
|
810 /// add the readed edges to the given Graph. It will use the given |
|
811 /// node id reader to read the source and target nodes of the edges. |
|
812 /// The reader will read the section only if the \c _id and the |
|
813 /// \c edgset_id are the same. |
|
814 template <typename NodeIdReader> |
|
815 EdgeSetReader(LemonReader& _reader, |
|
816 typename SmartParameter<Graph>::Type _graph, |
|
817 const NodeIdReader& _nodeIdReader, |
|
818 const std::string& _id = std::string(), |
|
819 const DefaultSkipper& _skipper = DefaultSkipper()) |
|
820 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), |
|
821 nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {} |
|
822 |
|
823 /// \brief Destructor. |
|
824 /// |
|
825 /// Destructor for EdgeSetReader. |
|
826 virtual ~EdgeSetReader() { |
|
827 for (typename MapReaders::iterator it = readers.begin(); |
|
828 it != readers.end(); ++it) { |
|
829 delete it->second; |
|
830 } |
|
831 } |
|
832 |
|
833 private: |
|
834 EdgeSetReader(const EdgeSetReader&); |
|
835 void operator=(const EdgeSetReader&); |
|
836 |
|
837 public: |
|
838 |
|
839 /// \brief Add a new edge map reader command for the reader. |
|
840 /// |
|
841 /// Add a new edge map reader command for the reader. |
|
842 template <typename Map> |
|
843 EdgeSetReader& readEdgeMap(std::string name, Map& map) { |
|
844 return _readMap< |
|
845 typename Traits::template Reader<typename Map::Value>, Map, |
|
846 typename SmartParameter<Map>::Type>(name, map); |
|
847 } |
|
848 |
|
849 template <typename Map> |
|
850 EdgeSetReader& readEdgeMap(std::string name, const Map& map) { |
|
851 return _readMap< |
|
852 typename Traits::template Reader<typename Map::Value>, Map, |
|
853 typename SmartParameter<Map>::Type>(name, map); |
|
854 } |
|
855 |
|
856 /// \brief Add a new edge map reader command for the reader. |
|
857 /// |
|
858 /// Add a new edge map reader command for the reader. |
|
859 template <typename Reader, typename Map> |
|
860 EdgeSetReader& readEdgeMap(std::string name, Map& map, |
|
861 const Reader& reader = Reader()) { |
|
862 return _readMap<Reader, Map, |
|
863 typename SmartParameter<Map>::Type>(name, map, reader); |
|
864 } |
|
865 |
|
866 template <typename Reader, typename Map> |
|
867 EdgeSetReader& readEdgeMap(std::string name, const Map& map, |
|
868 const Reader& reader = Reader()) { |
|
869 return _readMap<Reader, Map, |
|
870 typename SmartParameter<Map>::Type>(name, map, reader); |
|
871 } |
|
872 |
|
873 private: |
|
874 |
|
875 template <typename Reader, typename Map, typename MapParameter> |
|
876 EdgeSetReader& _readMap(std::string name, MapParameter map, |
|
877 const Reader& reader = Reader()) { |
|
878 if (readers.find(name) != readers.end()) { |
|
879 ErrorMessage msg; |
|
880 msg << "Multiple read rule for edge map: " << name; |
|
881 throw IOParameterError(msg.message()); |
|
882 } |
|
883 readers.insert( |
|
884 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader))); |
|
885 return *this; |
|
886 } |
|
887 |
|
888 public: |
|
889 |
|
890 /// \brief Add a new edge map skipper command for the reader. |
|
891 /// |
|
892 /// Add a new edge map skipper command for the reader. |
|
893 template <typename Reader> |
|
894 EdgeSetReader& skipEdgeMap(std::string name, |
|
895 const Reader& reader = Reader()) { |
|
896 if (readers.find(name) != readers.end()) { |
|
897 ErrorMessage msg; |
|
898 msg << "Multiple read rule for edge map: " << name; |
|
899 throw IOParameterError(msg.message()); |
|
900 } |
|
901 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader))); |
|
902 return *this; |
|
903 } |
|
904 |
|
905 protected: |
|
906 |
|
907 /// \brief Gives back true when the SectionReader can process |
|
908 /// the section with the given header line. |
|
909 /// |
|
910 /// It gives back true when the header line starts with \c \@edgeset, |
|
911 /// and the header line's id and the edgeset's id are the same. |
|
912 virtual bool header(const std::string& line) { |
|
913 std::istringstream ls(line); |
|
914 std::string command; |
|
915 std::string name; |
|
916 ls >> command >> name; |
|
917 return command == "@edgeset" && name == id; |
|
918 } |
|
919 |
|
920 /// \brief Reader function of the section. |
|
921 /// |
|
922 /// It reads the content of the section. |
|
923 virtual void read(std::istream& is) { |
|
924 std::vector<ReaderBase<Edge>* > index; |
|
925 std::string line; |
|
926 |
|
927 getline(is, line); |
|
928 std::istringstream ls(line); |
|
929 while (ls >> id) { |
|
930 typename MapReaders::iterator it = readers.find(id); |
|
931 if (it != readers.end()) { |
|
932 index.push_back(it->second); |
|
933 } else { |
|
934 index.push_back(&skipper); |
|
935 } |
|
936 if (id == "id" && inverter.get() == 0) { |
|
937 inverter.reset(index.back()->getInverter()); |
|
938 index.back() = inverter.get(); |
|
939 } |
|
940 } |
|
941 while (getline(is, line)) { |
|
942 std::istringstream ls(line); |
|
943 Node from = nodeIdReader->read(ls); |
|
944 Node to = nodeIdReader->read(ls); |
|
945 Edge edge = graph.addEdge(from, to); |
|
946 for (int i = 0; i < (int)index.size(); ++i) { |
|
947 index[i]->read(ls, edge); |
|
948 } |
|
949 } |
|
950 } |
|
951 |
|
952 public: |
|
953 |
|
954 /// \brief Returns true if the edgeset can give back the edge by its id. |
|
955 /// |
|
956 /// Returns true if the edgeset can give back the edge by its id. |
|
957 /// It is possible only if an "id" named map was read. |
|
958 bool isIdReader() const { |
|
959 return inverter.get() != 0; |
|
960 } |
|
961 |
|
962 /// \brief Gives back the edge by its id. |
|
963 /// |
|
964 /// It reads an id from the stream and gives back which edge belongs to |
|
965 /// it. It is possible only if there was read an "id" named map. |
|
966 Edge readId(std::istream& is, Edge = Edge()) const { |
|
967 return inverter->read(is); |
|
968 } |
|
969 |
|
970 private: |
|
971 |
|
972 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders; |
|
973 MapReaders readers; |
|
974 |
|
975 typename SmartReference<Graph>::Type graph; |
|
976 std::string id; |
|
977 SkipReader<Edge, DefaultSkipper> skipper; |
|
978 |
|
979 std::auto_ptr<InverterBase<Edge> > inverter; |
|
980 std::auto_ptr<IdReaderBase<Node> > nodeIdReader; |
|
981 }; |
|
982 |
|
983 /// \ingroup io_group |
|
984 /// \brief SectionReader for reading a undirected graph's edgeset. |
|
985 /// |
|
986 /// The lemon format can store multiple undirected edgesets with several |
|
987 /// maps. The undirected edgeset section's header line is \c \@undiredgeset |
|
988 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty. |
|
989 /// |
|
990 /// The first line of the section contains the names of the maps separated |
|
991 /// with white spaces. Each next lines describes an edge in the edgeset. The |
|
992 /// line contains the connected nodes' id and the mapped values for each map. |
|
993 /// |
|
994 /// The section can handle the directed as a syntactical sugar. Two |
|
995 /// undirected edge map describes one directed edge map. This two maps |
|
996 /// are the forward map and the backward map and the names of this map |
|
997 /// is near the same just with a prefix \c '+' or \c '-' character |
|
998 /// difference. |
|
999 /// |
|
1000 /// If the edgeset contains an \c "id" named map then it will be regarded |
|
1001 /// as id map. This map should contain only unique values and when the |
|
1002 /// \c readId() member will read a value from the given stream it will |
|
1003 /// give back that undiricted edge which is mapped to this value. |
|
1004 /// |
|
1005 /// The undirected edgeset reader needs a node id reader to identify which |
|
1006 /// nodes have to be connected. If a NodeSetReader reads an "id" named map, |
|
1007 /// it will be able to resolve the nodes by ids. |
|
1008 /// |
|
1009 /// \relates LemonReader |
|
1010 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
|
1011 class UndirEdgeSetReader : public CommonSectionReaderBase { |
|
1012 typedef CommonSectionReaderBase Parent; |
|
1013 public: |
|
1014 |
|
1015 typedef _Graph Graph; |
|
1016 typedef _Traits Traits; |
|
1017 typedef typename Graph::Node Node; |
|
1018 typedef typename Graph::Edge Edge; |
|
1019 typedef typename Graph::UndirEdge UndirEdge; |
|
1020 typedef typename Traits::Skipper DefaultSkipper; |
|
1021 |
|
1022 /// \brief Constructor. |
|
1023 /// |
|
1024 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader |
|
1025 /// and attach it into the given LemonReader. The undirected edgeset |
|
1026 /// reader will add the readed undirected edges to the given Graph. It |
|
1027 /// will use the given node id reader to read the source and target |
|
1028 /// nodes of the edges. The reader will read the section only if the |
|
1029 /// \c _id and the \c undiredgset_id are the same. |
|
1030 template <typename NodeIdReader> |
|
1031 UndirEdgeSetReader(LemonReader& _reader, |
|
1032 typename SmartParameter<Graph>::Type _graph, |
|
1033 const NodeIdReader& _nodeIdReader, |
|
1034 const std::string& _id = std::string(), |
|
1035 const DefaultSkipper& _skipper = DefaultSkipper()) |
|
1036 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), |
|
1037 nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {} |
|
1038 |
|
1039 /// \brief Destructor. |
|
1040 /// |
|
1041 /// Destructor for UndirEdgeSetReader. |
|
1042 virtual ~UndirEdgeSetReader() { |
|
1043 for (typename MapReaders::iterator it = readers.begin(); |
|
1044 it != readers.end(); ++it) { |
|
1045 delete it->second; |
|
1046 } |
|
1047 } |
|
1048 |
|
1049 private: |
|
1050 UndirEdgeSetReader(const UndirEdgeSetReader&); |
|
1051 void operator=(const UndirEdgeSetReader&); |
|
1052 |
|
1053 public: |
|
1054 |
|
1055 /// \brief Add a new undirected edge map reader command for the reader. |
|
1056 /// |
|
1057 /// Add a new edge undirected map reader command for the reader. |
|
1058 template <typename Map> |
|
1059 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) { |
|
1060 return _readMap< |
|
1061 typename Traits::template Reader<typename Map::Value>, Map, |
|
1062 typename SmartParameter<Map>::Type>(name, map); |
|
1063 } |
|
1064 |
|
1065 template <typename Map> |
|
1066 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) { |
|
1067 return _readMap< |
|
1068 typename Traits::template Reader<typename Map::Value>, Map, |
|
1069 typename SmartParameter<Map>::Type>(name, map); |
|
1070 } |
|
1071 |
|
1072 /// \brief Add a new undirected edge map reader command for the reader. |
|
1073 /// |
|
1074 /// Add a new edge undirected map reader command for the reader. |
|
1075 template <typename Reader, typename Map> |
|
1076 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, |
|
1077 const Reader& reader = Reader()) { |
|
1078 return _readMap<Reader, Map, typename SmartParameter<Map>::Type> |
|
1079 (name, map, reader); |
|
1080 } |
|
1081 |
|
1082 template <typename Reader, typename Map> |
|
1083 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, |
|
1084 const Reader& reader = Reader()) { |
|
1085 return _readMap<Reader, Map, typename SmartParameter<Map>::Type > |
|
1086 (name, map, reader); |
|
1087 } |
|
1088 |
|
1089 private: |
|
1090 |
|
1091 template <typename Reader, typename Map, typename MapParameter> |
|
1092 UndirEdgeSetReader& _readMap(std::string name, MapParameter map, |
|
1093 const Reader& reader = Reader()) { |
|
1094 if (readers.find(name) != readers.end()) { |
|
1095 ErrorMessage msg; |
|
1096 msg << "Multiple read rule for edge map: " << name; |
|
1097 throw IOParameterError(msg.message()); |
|
1098 } |
|
1099 readers.insert( |
|
1100 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader))); |
|
1101 return *this; |
|
1102 } |
|
1103 |
|
1104 public: |
|
1105 |
|
1106 /// \brief Add a new undirected edge map skipper command for the reader. |
|
1107 /// |
|
1108 /// Add a new undirected edge map skipper command for the reader. |
|
1109 template <typename Reader> |
|
1110 UndirEdgeSetReader& skipUndirEdgeMap(std::string name, |
|
1111 const Reader& reader = Reader()) { |
|
1112 if (readers.find(name) != readers.end()) { |
|
1113 ErrorMessage msg; |
|
1114 msg << "Multiple read rule for node map: " << name; |
|
1115 throw IOParameterError(msg.message()); |
|
1116 } |
|
1117 readers.insert(make_pair(name, |
|
1118 new SkipReader<UndirEdge, Reader>(reader))); |
|
1119 return *this; |
|
1120 } |
|
1121 |
|
1122 /// \brief Add a new directed edge map reader command for the reader. |
|
1123 /// |
|
1124 /// Add a new directed edge map reader command for the reader. |
|
1125 template <typename Map> |
|
1126 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) { |
|
1127 return _readDirMap< |
|
1128 typename Traits::template Reader<typename Map::Value>, Map, |
|
1129 typename SmartParameter<Map>::Type>(name, map); |
|
1130 } |
|
1131 |
|
1132 template <typename Map> |
|
1133 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) { |
|
1134 return _readDirMap< |
|
1135 typename Traits::template Reader<typename Map::Value>, Map, |
|
1136 typename SmartParameter<Map>::Type>(name, map); |
|
1137 } |
|
1138 |
|
1139 /// \brief Add a new directed edge map reader command for the reader. |
|
1140 /// |
|
1141 /// Add a new directed edge map reader command for the reader. |
|
1142 template <typename Reader, typename Map> |
|
1143 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, |
|
1144 const Reader& reader = Reader()) { |
|
1145 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type> |
|
1146 (name, map, reader); |
|
1147 } |
|
1148 |
|
1149 template <typename Reader, typename Map> |
|
1150 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, |
|
1151 const Reader& reader = Reader()) { |
|
1152 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type> |
|
1153 (name, map, reader); |
|
1154 } |
|
1155 |
|
1156 private: |
|
1157 |
|
1158 template <typename Reader, typename Map, typename MapParameter> |
|
1159 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map, |
|
1160 const Reader& reader = Reader()) { |
|
1161 readMap("+" + name, |
|
1162 _reader_bits::writeComposeMap(map, forwardMap(graph)), reader); |
|
1163 readMap("-" + name, |
|
1164 _reader_bits::writeComposeMap(map, backwardMap(graph)), reader); |
|
1165 return *this; |
|
1166 } |
|
1167 |
|
1168 public: |
|
1169 |
|
1170 /// \brief Add a new directed edge map skipper command for the reader. |
|
1171 /// |
|
1172 /// Add a new directed edge map skipper command for the reader. |
|
1173 template <typename Reader> |
|
1174 UndirEdgeSetReader& skipEdgeMap(std::string name, |
|
1175 const Reader& reader = Reader()) { |
|
1176 skipMap("+" + name, reader); |
|
1177 skipMap("-" + name, reader); |
|
1178 return *this; |
|
1179 } |
|
1180 |
|
1181 protected: |
|
1182 |
|
1183 /// \brief Gives back true when the SectionReader can process |
|
1184 /// the section with the given header line. |
|
1185 /// |
|
1186 /// It gives back true when the header line starts with \c \@undiredgeset, |
|
1187 /// and the header line's id and the edgeset's id are the same. |
|
1188 virtual bool header(const std::string& line) { |
|
1189 std::istringstream ls(line); |
|
1190 std::string command; |
|
1191 std::string name; |
|
1192 ls >> command >> name; |
|
1193 return command == "@undiredgeset" && name == id; |
|
1194 } |
|
1195 |
|
1196 /// \brief Reader function of the section. |
|
1197 /// |
|
1198 /// It reads the content of the section. |
|
1199 virtual void read(std::istream& is) { |
|
1200 std::vector<ReaderBase<UndirEdge>* > index; |
|
1201 std::string line; |
|
1202 |
|
1203 getline(is, line); |
|
1204 std::istringstream ls(line); |
|
1205 while (ls >> id) { |
|
1206 typename MapReaders::iterator it = readers.find(id); |
|
1207 if (it != readers.end()) { |
|
1208 index.push_back(it->second); |
|
1209 } else { |
|
1210 index.push_back(&skipper); |
|
1211 } |
|
1212 if (id == "id" && inverter.get() == 0) { |
|
1213 inverter.reset(index.back()->getInverter()); |
|
1214 index.back() = inverter.get(); |
|
1215 } |
|
1216 } |
|
1217 while (getline(is, line)) { |
|
1218 std::istringstream ls(line); |
|
1219 Node from = nodeIdReader->read(ls); |
|
1220 Node to = nodeIdReader->read(ls); |
|
1221 UndirEdge edge = graph.addEdge(from, to); |
|
1222 for (int i = 0; i < (int)index.size(); ++i) { |
|
1223 index[i]->read(ls, edge); |
|
1224 } |
|
1225 } |
|
1226 } |
|
1227 |
|
1228 public: |
|
1229 |
|
1230 /// \brief Returns true if the edgeset can give back the edge by its id. |
|
1231 /// |
|
1232 /// Returns true if the edgeset can give back the undirected edge by its |
|
1233 /// id. It is possible only if an "id" named map was read. |
|
1234 bool isIdReader() const { |
|
1235 return inverter.get() != 0; |
|
1236 } |
|
1237 |
|
1238 /// \brief Gives back the undirected edge by its id. |
|
1239 /// |
|
1240 /// It reads an id from the stream and gives back which undirected edge |
|
1241 /// belongs to it. It is possible only if there was read an "id" named map. |
|
1242 UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const { |
|
1243 return inverter->read(is); |
|
1244 } |
|
1245 |
|
1246 /// \brief Gives back the directed edge by its id. |
|
1247 /// |
|
1248 /// It reads an id from the stream and gives back which directed edge |
|
1249 /// belongs to it. The directed edge id is the \c '+' or \c '-' character |
|
1250 /// and the undirected edge id. It is possible only if there was read |
|
1251 /// an "id" named map. |
|
1252 Edge readId(std::istream& is, Edge = Edge()) const { |
|
1253 char c; |
|
1254 is >> c; |
|
1255 UndirEdge undirEdge = inverter->read(is); |
|
1256 if (c == '+') { |
|
1257 return graph.edgeWithSource(undirEdge, graph.source(undirEdge)); |
|
1258 } else if (c == '-') { |
|
1259 return graph.edgeWithSource(undirEdge, graph.target(undirEdge)); |
|
1260 } else { |
|
1261 throw DataFormatError("Wrong id format for edge " |
|
1262 "in undirected edgeset"); |
|
1263 } |
|
1264 } |
|
1265 |
|
1266 private: |
|
1267 |
|
1268 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders; |
|
1269 MapReaders readers; |
|
1270 |
|
1271 typename SmartReference<Graph>::Type graph; |
|
1272 std::string id; |
|
1273 SkipReader<UndirEdge, DefaultSkipper> skipper; |
|
1274 |
|
1275 std::auto_ptr<InverterBase<UndirEdge> > inverter; |
|
1276 std::auto_ptr<IdReaderBase<Node> > nodeIdReader; |
|
1277 }; |
|
1278 |
|
1279 /// \ingroup io_group |
|
1280 /// \brief SectionReader for reading labeled nodes. |
|
1281 /// |
|
1282 /// The nodes section's header line is \c \@nodes \c nodes_id, but the |
|
1283 /// \c nodes_id may be empty. |
|
1284 /// |
|
1285 /// Each line in the section contains the name of the node |
|
1286 /// and then the node id. |
|
1287 /// |
|
1288 /// \relates LemonReader |
|
1289 template <typename _Graph> |
|
1290 class NodeReader : public CommonSectionReaderBase { |
|
1291 typedef CommonSectionReaderBase Parent; |
|
1292 typedef _Graph Graph; |
|
1293 typedef typename Graph::Node Node; |
|
1294 public: |
|
1295 |
|
1296 /// \brief Constructor. |
|
1297 /// |
|
1298 /// Constructor for NodeReader. It creates the NodeReader and |
|
1299 /// attach it into the given LemonReader. It will use the given |
|
1300 /// node id reader to give back the nodes. The reader will read the |
|
1301 /// section only if the \c _id and the \c nodes_id are the same. |
|
1302 template <typename _IdReader> |
|
1303 NodeReader(LemonReader& _reader, const _IdReader& _idReader, |
|
1304 const std::string& _id = std::string()) |
|
1305 : Parent(_reader), id(_id), |
|
1306 idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} |
|
1307 |
|
1308 /// \brief Destructor. |
|
1309 /// |
|
1310 /// Destructor for NodeReader. |
|
1311 virtual ~NodeReader() {} |
|
1312 |
|
1313 private: |
|
1314 NodeReader(const NodeReader&); |
|
1315 void operator=(const NodeReader&); |
|
1316 |
|
1317 public: |
|
1318 |
|
1319 /// \brief Add a node reader command for the NodeReader. |
|
1320 /// |
|
1321 /// Add a node reader command for the NodeReader. |
|
1322 void readNode(const std::string& name, Node& item) { |
|
1323 if (readers.find(name) != readers.end()) { |
|
1324 ErrorMessage msg; |
|
1325 msg << "Multiple read rule for node: " << name; |
|
1326 throw IOParameterError(msg.message()); |
|
1327 } |
|
1328 readers.insert(make_pair(name, &item)); |
|
1329 } |
|
1330 |
|
1331 protected: |
|
1332 |
|
1333 /// \brief Gives back true when the SectionReader can process |
|
1334 /// the section with the given header line. |
|
1335 /// |
|
1336 /// It gives back true when the header line start with \c \@nodes, |
|
1337 /// and the header line's id and the reader's id are the same. |
|
1338 virtual bool header(const std::string& line) { |
|
1339 std::istringstream ls(line); |
|
1340 std::string command; |
|
1341 std::string name; |
|
1342 ls >> command >> name; |
|
1343 return command == "@nodes" && name == id; |
|
1344 } |
|
1345 |
|
1346 /// \brief Reader function of the section. |
|
1347 /// |
|
1348 /// It reads the content of the section. |
|
1349 virtual void read(std::istream& is) { |
|
1350 std::string line; |
|
1351 while (getline(is, line)) { |
|
1352 std::istringstream ls(line); |
|
1353 std::string id; |
|
1354 ls >> id; |
|
1355 typename NodeReaders::iterator it = readers.find(id); |
|
1356 if (it != readers.end()) { |
|
1357 *(it->second) = idReader->read(ls); |
|
1358 } |
|
1359 } |
|
1360 } |
|
1361 |
|
1362 private: |
|
1363 |
|
1364 std::string id; |
|
1365 |
|
1366 typedef std::map<std::string, Node*> NodeReaders; |
|
1367 NodeReaders readers; |
|
1368 std::auto_ptr<IdReaderBase<Node> > idReader; |
|
1369 }; |
|
1370 |
|
1371 /// \ingroup io_group |
|
1372 /// \brief SectionReader for reading labeled edges. |
|
1373 /// |
|
1374 /// The edges section's header line is \c \@edges \c edges_id, but the |
|
1375 /// \c edges_id may be empty. |
|
1376 /// |
|
1377 /// Each line in the section contains the name of the edge |
|
1378 /// and then the edge id. |
|
1379 /// |
|
1380 /// \relates LemonReader |
|
1381 template <typename _Graph> |
|
1382 class EdgeReader : public CommonSectionReaderBase { |
|
1383 typedef CommonSectionReaderBase Parent; |
|
1384 typedef _Graph Graph; |
|
1385 typedef typename Graph::Edge Edge; |
|
1386 public: |
|
1387 |
|
1388 /// \brief Constructor. |
|
1389 /// |
|
1390 /// Constructor for EdgeReader. It creates the EdgeReader and |
|
1391 /// attach it into the given LemonReader. It will use the given |
|
1392 /// edge id reader to give back the edges. The reader will read the |
|
1393 /// section only if the \c _id and the \c edges_id are the same. |
|
1394 template <typename _IdReader> |
|
1395 EdgeReader(LemonReader& _reader, const _IdReader& _idReader, |
|
1396 const std::string& _id = std::string()) |
|
1397 : Parent(_reader), id(_id), |
|
1398 idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} |
|
1399 |
|
1400 /// \brief Destructor. |
|
1401 /// |
|
1402 /// Destructor for EdgeReader. |
|
1403 virtual ~EdgeReader() {} |
|
1404 private: |
|
1405 EdgeReader(const EdgeReader&); |
|
1406 void operator=(const EdgeReader&); |
|
1407 |
|
1408 public: |
|
1409 |
|
1410 /// \brief Add an edge reader command for the EdgeReader. |
|
1411 /// |
|
1412 /// Add an edge reader command for the EdgeReader. |
|
1413 void readEdge(const std::string& name, Edge& item) { |
|
1414 if (readers.find(name) != readers.end()) { |
|
1415 ErrorMessage msg; |
|
1416 msg << "Multiple read rule for edge: " << name; |
|
1417 throw IOParameterError(msg.message()); |
|
1418 } |
|
1419 readers.insert(make_pair(name, &item)); |
|
1420 } |
|
1421 |
|
1422 protected: |
|
1423 |
|
1424 /// \brief Gives back true when the SectionReader can process |
|
1425 /// the section with the given header line. |
|
1426 /// |
|
1427 /// It gives back true when the header line start with \c \@edges, |
|
1428 /// and the header line's id and the reader's id are the same. |
|
1429 virtual bool header(const std::string& line) { |
|
1430 std::istringstream ls(line); |
|
1431 std::string command; |
|
1432 std::string name; |
|
1433 ls >> command >> name; |
|
1434 return command == "@edges" && name == id; |
|
1435 } |
|
1436 |
|
1437 /// \brief Reader function of the section. |
|
1438 /// |
|
1439 /// It reads the content of the section. |
|
1440 virtual void read(std::istream& is) { |
|
1441 std::string line; |
|
1442 while (getline(is, line)) { |
|
1443 std::istringstream ls(line); |
|
1444 std::string id; |
|
1445 ls >> id; |
|
1446 typename EdgeReaders::iterator it = readers.find(id); |
|
1447 if (it != readers.end()) { |
|
1448 *(it->second) = idReader->read(ls); |
|
1449 } |
|
1450 } |
|
1451 } |
|
1452 |
|
1453 private: |
|
1454 |
|
1455 std::string id; |
|
1456 |
|
1457 typedef std::map<std::string, Edge*> EdgeReaders; |
|
1458 EdgeReaders readers; |
|
1459 std::auto_ptr<IdReaderBase<Edge> > idReader; |
|
1460 }; |
|
1461 |
|
1462 /// \ingroup io_group |
|
1463 /// \brief SectionReader for reading labeled undirected edges. |
|
1464 /// |
|
1465 /// The undirected edges section's header line is \c \@undiredges |
|
1466 /// \c undiredges_id, but the \c undiredges_id may be empty. |
|
1467 /// |
|
1468 /// Each line in the section contains the name of the undirected edge |
|
1469 /// and then the undirected edge id. |
|
1470 /// |
|
1471 /// \relates LemonReader |
|
1472 template <typename _Graph> |
|
1473 class UndirEdgeReader : public CommonSectionReaderBase { |
|
1474 typedef CommonSectionReaderBase Parent; |
|
1475 typedef _Graph Graph; |
|
1476 typedef typename Graph::Edge Edge; |
|
1477 typedef typename Graph::UndirEdge UndirEdge; |
|
1478 public: |
|
1479 |
|
1480 /// \brief Constructor. |
|
1481 /// |
|
1482 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and |
|
1483 /// attach it into the given LemonReader. It will use the given |
|
1484 /// undirected edge id reader to give back the edges. The reader will |
|
1485 /// read the section only if the \c _id and the \c undiredges_id are |
|
1486 /// the same. |
|
1487 template <typename _IdReader> |
|
1488 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, |
|
1489 const std::string& _id = std::string()) |
|
1490 : Parent(_reader), id(_id), |
|
1491 undirEdgeIdReader(new IdReader<UndirEdge, _IdReader>(_idReader)), |
|
1492 edgeIdReader(new IdReader<Edge, _IdReader>(_idReader)) |
|
1493 {} |
|
1494 |
|
1495 /// \brief Destructor. |
|
1496 /// |
|
1497 /// Destructor for UndirEdgeReader. |
|
1498 virtual ~UndirEdgeReader() {} |
|
1499 private: |
|
1500 UndirEdgeReader(const UndirEdgeReader&); |
|
1501 void operator=(const UndirEdgeReader&); |
|
1502 |
|
1503 public: |
|
1504 |
|
1505 /// \brief Add an undirected edge reader command for the UndirEdgeReader. |
|
1506 /// |
|
1507 /// Add an undirected edge reader command for the UndirEdgeReader. |
|
1508 void readUndirEdge(const std::string& name, UndirEdge& item) { |
|
1509 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) { |
|
1510 ErrorMessage msg; |
|
1511 msg << "Multiple read rule for undirected edge: " << name; |
|
1512 throw IOParameterError(msg.message()); |
|
1513 } |
|
1514 undirEdgeReaders.insert(make_pair(name, &item)); |
|
1515 } |
|
1516 |
|
1517 /// \brief Add an edge reader command for the UndirEdgeReader. |
|
1518 /// |
|
1519 /// Add an edge reader command for the UndirEdgeReader. |
|
1520 void readEdge(const std::string& name, Edge& item) { |
|
1521 if (edgeReaders.find(name) != edgeReaders.end()) { |
|
1522 ErrorMessage msg; |
|
1523 msg << "Multiple read rule for edge: " << name; |
|
1524 throw IOParameterError(msg.message()); |
|
1525 } |
|
1526 edgeReaders.insert(make_pair(name, &item)); |
|
1527 } |
|
1528 |
|
1529 protected: |
|
1530 |
|
1531 /// \brief Gives back true when the SectionReader can process |
|
1532 /// the section with the given header line. |
|
1533 /// |
|
1534 /// It gives back true when the header line start with \c \@edges, |
|
1535 /// and the header line's id and the reader's id are the same. |
|
1536 virtual bool header(const std::string& line) { |
|
1537 std::istringstream ls(line); |
|
1538 std::string command; |
|
1539 std::string name; |
|
1540 ls >> command >> name; |
|
1541 return command == "@undiredges" && name == id; |
|
1542 } |
|
1543 |
|
1544 /// \brief Reader function of the section. |
|
1545 /// |
|
1546 /// It reads the content of the section. |
|
1547 virtual void read(std::istream& is) { |
|
1548 std::string line; |
|
1549 while (getline(is, line)) { |
|
1550 std::istringstream ls(line); |
|
1551 std::string id; |
|
1552 ls >> id; |
|
1553 { |
|
1554 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id); |
|
1555 if (it != undirEdgeReaders.end()) { |
|
1556 *(it->second) = undirEdgeIdReader->read(ls); |
|
1557 break; |
|
1558 } |
|
1559 } { |
|
1560 typename EdgeReaders::iterator it = edgeReaders.find(id); |
|
1561 if (it != edgeReaders.end()) { |
|
1562 *(it->second) = edgeIdReader->read(ls); |
|
1563 break; |
|
1564 } |
|
1565 } |
|
1566 } |
|
1567 } |
|
1568 |
|
1569 private: |
|
1570 |
|
1571 std::string id; |
|
1572 |
|
1573 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders; |
|
1574 UndirEdgeReaders undirEdgeReaders; |
|
1575 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader; |
|
1576 |
|
1577 typedef std::map<std::string, Edge*> EdgeReaders; |
|
1578 EdgeReaders edgeReaders; |
|
1579 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader; |
|
1580 }; |
|
1581 |
|
1582 /// \ingroup io_group |
|
1583 /// \brief SectionReader for attributes. |
|
1584 /// |
|
1585 /// The lemon format can store multiple attribute set. Each set has |
|
1586 /// the header line \c \@attributes \c attributeset_id, but the |
|
1587 /// attributeset_id may be empty. |
|
1588 /// |
|
1589 /// The attributeset section contains several lines. Each of them starts |
|
1590 /// with an attribute and then a the value for the id. |
|
1591 /// |
|
1592 /// \relates LemonReader |
|
1593 template <typename _Traits = DefaultReaderTraits> |
|
1594 class AttributeReader : public CommonSectionReaderBase { |
|
1595 typedef CommonSectionReaderBase Parent; |
|
1596 typedef _Traits Traits; |
|
1597 public: |
|
1598 /// \brief Constructor. |
|
1599 /// |
|
1600 /// Constructor for AttributeReader. It creates the AttributeReader and |
|
1601 /// attach it into the given LemonReader. The reader process a section |
|
1602 /// only if the \c section_id and the \c _id are the same. |
|
1603 AttributeReader(LemonReader& _reader, |
|
1604 const std::string& _id = std::string()) |
|
1605 : Parent(_reader), id(_id) {} |
|
1606 |
|
1607 /// \brief Destructor. |
|
1608 /// |
|
1609 /// Destructor for AttributeReader. |
|
1610 virtual ~AttributeReader() { |
|
1611 for (typename Readers::iterator it = readers.begin(); |
|
1612 it != readers.end(); ++it) { |
|
1613 delete it->second; |
|
1614 } |
|
1615 } |
|
1616 |
|
1617 private: |
|
1618 AttributeReader(const AttributeReader&); |
|
1619 void operator=(AttributeReader&); |
|
1620 |
|
1621 public: |
|
1622 /// \brief Add an attribute reader command for the reader. |
|
1623 /// |
|
1624 /// Add an attribute reader command for the reader. |
|
1625 template <typename Value> |
|
1626 AttributeReader& readAttribute(const std::string& id, Value& value) { |
|
1627 return readAttribute<typename Traits::template Reader<Value> > |
|
1628 (id, value); |
|
1629 } |
|
1630 |
|
1631 /// \brief Add an attribute reader command for the reader. |
|
1632 /// |
|
1633 /// Add an attribute reader command for the reader. |
|
1634 template <typename Reader, typename Value> |
|
1635 AttributeReader& readAttribute(const std::string& name, Value& value, |
|
1636 const Reader& reader = Reader()) { |
|
1637 if (readers.find(name) != readers.end()) { |
|
1638 ErrorMessage msg; |
|
1639 msg << "Multiple read rule for attribute: " << name; |
|
1640 throw IOParameterError(msg.message()); |
|
1641 } |
|
1642 readers.insert(make_pair(name, new ValueReader<Value, Reader> |
|
1643 (value, reader))); |
|
1644 return *this; |
|
1645 } |
|
1646 |
|
1647 protected: |
|
1648 |
|
1649 /// \brief Gives back true when the SectionReader can process |
|
1650 /// the section with the given header line. |
|
1651 /// |
|
1652 /// It gives back true when the header line start with \c \@attributes, |
|
1653 /// and the header line's id and the attributeset's id are the same. |
|
1654 bool header(const std::string& line) { |
|
1655 std::istringstream ls(line); |
|
1656 std::string command; |
|
1657 std::string name; |
|
1658 ls >> command >> name; |
|
1659 return command == "@attributes" && name == id; |
|
1660 } |
|
1661 |
|
1662 /// \brief Reader function of the section. |
|
1663 /// |
|
1664 /// It reads the content of the section. |
|
1665 void read(std::istream& is) { |
|
1666 std::string line; |
|
1667 while (getline(is, line)) { |
|
1668 std::istringstream ls(line); |
|
1669 std::string id; |
|
1670 ls >> id; |
|
1671 typename Readers::iterator it = readers.find(id); |
|
1672 if (it != readers.end()) { |
|
1673 it->second->read(ls); |
|
1674 } |
|
1675 } |
|
1676 } |
|
1677 |
|
1678 private: |
|
1679 std::string id; |
|
1680 |
|
1681 typedef std::map<std::string, ValueReaderBase*> Readers; |
|
1682 Readers readers; |
|
1683 }; |
|
1684 |
|
1685 /// \ingroup io_group |
|
1686 /// \brief SectionReader for retrieve what is in the file. |
|
1687 /// |
|
1688 /// SectionReader for retrieve what is in the file. If you want |
|
1689 /// to know which sections, maps and items are in the file |
|
1690 /// use the next code: |
|
1691 /// \code |
|
1692 /// LemonReader reader("input.lgf"); |
|
1693 /// ContentReader content(reader); |
|
1694 /// reader.run(); |
|
1695 /// \endcode |
|
1696 class ContentReader : public LemonReader::SectionReader { |
|
1697 typedef LemonReader::SectionReader Parent; |
|
1698 public: |
|
1699 /// \brief Constructor. |
|
1700 /// |
|
1701 /// Constructor for |
|
1702 ContentReader(LemonReader& _reader) : Parent(_reader) {} |
|
1703 |
|
1704 /// \brief Desctructor. |
|
1705 /// |
|
1706 /// Desctructor. |
|
1707 virtual ~ContentReader() {} |
|
1708 |
|
1709 /// \brief Gives back how many nodesets are in the file. |
|
1710 /// |
|
1711 /// Gives back how many nodesets are in the file. |
|
1712 int nodeSetNum() const { |
|
1713 return nodesets.size(); |
|
1714 } |
|
1715 |
|
1716 /// \brief Gives back the name of nodeset on the indiced position. |
|
1717 /// |
|
1718 /// Gives back the name of nodeset on the indiced position. |
|
1719 std::string nodeSetName(int index) const { |
|
1720 return nodesets[index].name; |
|
1721 } |
|
1722 |
|
1723 /// \brief Gives back the map names of nodeset on the indiced position. |
|
1724 /// |
|
1725 /// Gives back the map names of nodeset on the indiced position. |
|
1726 const std::vector<std::string>& nodeSetMaps(int index) const { |
|
1727 return nodesets[index].items; |
|
1728 } |
|
1729 |
|
1730 /// \brief Gives back how many edgesets are in the file. |
|
1731 /// |
|
1732 /// Gives back how many edgesets are in the file. |
|
1733 int edgeSetNum() const { |
|
1734 return edgesets.size(); |
|
1735 } |
|
1736 |
|
1737 /// \brief Gives back the name of edgeset on the indiced position. |
|
1738 /// |
|
1739 /// Gives back the name of edgeset on the indiced position. |
|
1740 std::string edgeSetName(int index) const { |
|
1741 return edgesets[index].name; |
|
1742 } |
|
1743 |
|
1744 /// \brief Gives back the map names of edgeset on the indiced position. |
|
1745 /// |
|
1746 /// Gives back the map names of edgeset on the indiced position. |
|
1747 const std::vector<std::string>& edgeSetMaps(int index) const { |
|
1748 return edgesets[index].items; |
|
1749 } |
|
1750 |
|
1751 /// \brief Gives back how many undirected edgesets are in the file. |
|
1752 /// |
|
1753 /// Gives back how many undirected edgesets are in the file. |
|
1754 int undirEdgeSetNum() const { |
|
1755 return undiredgesets.size(); |
|
1756 } |
|
1757 |
|
1758 /// \brief Gives back the name of undirected edgeset on the indiced |
|
1759 /// position. |
|
1760 /// |
|
1761 /// Gives back the name of undirected edgeset on the indiced position. |
|
1762 std::string undirEdgeSetName(int index) const { |
|
1763 return undiredgesets[index].name; |
|
1764 } |
|
1765 |
|
1766 /// \brief Gives back the map names of undirected edgeset on the indiced |
|
1767 /// position. |
|
1768 /// |
|
1769 /// Gives back the map names of undirected edgeset on the indiced position. |
|
1770 const std::vector<std::string>& undirEdgeSetMaps(int index) const { |
|
1771 return undiredgesets[index].items; |
|
1772 } |
|
1773 |
|
1774 /// \brief Gives back how many labeled nodes section are in the file. |
|
1775 /// |
|
1776 /// Gives back how many labeled nodes section are in the file. |
|
1777 int nodesNum() const { |
|
1778 return nodes.size(); |
|
1779 } |
|
1780 |
|
1781 /// \brief Gives back the name of labeled nodes section on the indiced |
|
1782 /// position. |
|
1783 /// |
|
1784 /// Gives back the name of labeled nodes section on the indiced position. |
|
1785 std::string nodesName(int index) const { |
|
1786 return nodes[index].name; |
|
1787 } |
|
1788 |
|
1789 /// \brief Gives back the names of the labeled nodes in the indiced |
|
1790 /// section. |
|
1791 /// |
|
1792 /// Gives back the names of the labeled nodes in the indiced section. |
|
1793 const std::vector<std::string>& nodesItems(int index) const { |
|
1794 return nodes[index].items; |
|
1795 } |
|
1796 |
|
1797 /// \brief Gives back how many labeled edges section are in the file. |
|
1798 /// |
|
1799 /// Gives back how many labeled edges section are in the file. |
|
1800 int edgesNum() const { |
|
1801 return edges.size(); |
|
1802 } |
|
1803 |
|
1804 /// \brief Gives back the name of labeled edges section on the indiced |
|
1805 /// position. |
|
1806 /// |
|
1807 /// Gives back the name of labeled edges section on the indiced position. |
|
1808 std::string edgesName(int index) const { |
|
1809 return edges[index].name; |
|
1810 } |
|
1811 |
|
1812 /// \brief Gives back the names of the labeled edges in the indiced |
|
1813 /// section. |
|
1814 /// |
|
1815 /// Gives back the names of the labeled edges in the indiced section. |
|
1816 const std::vector<std::string>& edgesItems(int index) const { |
|
1817 return edges[index].items; |
|
1818 } |
|
1819 |
|
1820 /// \brief Gives back how many labeled undirected edges section are |
|
1821 /// in the file. |
|
1822 /// |
|
1823 /// Gives back how many labeled undirected edges section are in the file. |
|
1824 int undirEdgesNum() const { |
|
1825 return undiredges.size(); |
|
1826 } |
|
1827 |
|
1828 /// \brief Gives back the name of labeled undirected edges section |
|
1829 /// on the indiced position. |
|
1830 /// |
|
1831 /// Gives back the name of labeled undirected edges section on the |
|
1832 /// indiced position. |
|
1833 std::string undirEdgesName(int index) const { |
|
1834 return undiredges[index].name; |
|
1835 } |
|
1836 |
|
1837 /// \brief Gives back the names of the labeled undirected edges in |
|
1838 /// the indiced section. |
|
1839 /// |
|
1840 /// Gives back the names of the labeled undirected edges in the |
|
1841 /// indiced section. |
|
1842 const std::vector<std::string>& undirEdgesItems(int index) const { |
|
1843 return undiredges[index].items; |
|
1844 } |
|
1845 |
|
1846 |
|
1847 /// \brief Gives back how many attributes section are in the file. |
|
1848 /// |
|
1849 /// Gives back how many attributes section are in the file. |
|
1850 int attributesNum() const { |
|
1851 return attributes.size(); |
|
1852 } |
|
1853 |
|
1854 /// \brief Gives back the name of attributes section on the indiced |
|
1855 /// position. |
|
1856 /// |
|
1857 /// Gives back the name of attributes section on the indiced position. |
|
1858 std::string attributesName(int index) const { |
|
1859 return attributes[index].name; |
|
1860 } |
|
1861 |
|
1862 /// \brief Gives back the names of the attributes in the indiced section. |
|
1863 /// |
|
1864 /// Gives back the names of the attributes in the indiced section. |
|
1865 const std::vector<std::string>& attributesItems(int index) const { |
|
1866 return attributes[index].items; |
|
1867 } |
|
1868 |
|
1869 const std::vector<std::string>& otherSections() const { |
|
1870 return sections; |
|
1871 } |
|
1872 |
|
1873 protected: |
|
1874 |
|
1875 /// \brief Gives back true when the SectionReader can process |
|
1876 /// the section with the given header line. |
|
1877 /// |
|
1878 /// It gives back true when the section is common section. |
|
1879 bool header(const std::string& line) { |
|
1880 std::istringstream ls(line); |
|
1881 std::string command, name; |
|
1882 ls >> command >> name; |
|
1883 if (command == "@nodeset") { |
|
1884 current = command; |
|
1885 nodesets.push_back(SectionInfo(name)); |
|
1886 } else if (command == "@edgeset") { |
|
1887 current = command; |
|
1888 edgesets.push_back(SectionInfo(name)); |
|
1889 } else if (command == "@undiredgeset") { |
|
1890 current = command; |
|
1891 undiredgesets.push_back(SectionInfo(name)); |
|
1892 } else if (command == "@nodes") { |
|
1893 current = command; |
|
1894 nodes.push_back(SectionInfo(name)); |
|
1895 } else if (command == "@edges") { |
|
1896 current = command; |
|
1897 edges.push_back(SectionInfo(name)); |
|
1898 } else if (command == "@undiredges") { |
|
1899 current = command; |
|
1900 undiredges.push_back(SectionInfo(name)); |
|
1901 } else if (command == "@attributes") { |
|
1902 current = command; |
|
1903 attributes.push_back(SectionInfo(name)); |
|
1904 } else { |
|
1905 sections.push_back(line); |
|
1906 return false; |
|
1907 } |
|
1908 return true; |
|
1909 } |
|
1910 |
|
1911 /// \brief Retrieve the items from various sections. |
|
1912 /// |
|
1913 /// Retrieve the items from various sections. |
|
1914 void read(std::istream& is) { |
|
1915 if (current == "@nodeset") { |
|
1916 readMapNames(is, nodesets.back().items); |
|
1917 } else if (current == "@edgeset") { |
|
1918 readMapNames(is, edgesets.back().items); |
|
1919 } else if (current == "@undiredgeset") { |
|
1920 readMapNames(is, undiredgesets.back().items); |
|
1921 } else if (current == "@nodes") { |
|
1922 readItemNames(is, nodes.back().items); |
|
1923 } else if (current == "@edges") { |
|
1924 readItemNames(is, edges.back().items); |
|
1925 } else if (current == "@undiredges") { |
|
1926 readItemNames(is, undiredges.back().items); |
|
1927 } else if (current == "@attributes") { |
|
1928 readItemNames(is, attributes.back().items); |
|
1929 } |
|
1930 } |
|
1931 |
|
1932 private: |
|
1933 |
|
1934 void readMapNames(std::istream& is, std::vector<std::string>& maps) { |
|
1935 std::string line, id; |
|
1936 std::getline(is, line); |
|
1937 std::istringstream ls(line); |
|
1938 while (ls >> id) { |
|
1939 maps.push_back(id); |
|
1940 } |
|
1941 while (getline(is, line)); |
|
1942 } |
|
1943 |
|
1944 void readItemNames(std::istream& is, std::vector<std::string>& maps) { |
|
1945 std::string line, id; |
|
1946 while (std::getline(is, line)) { |
|
1947 std::istringstream ls(line); |
|
1948 ls >> id; |
|
1949 maps.push_back(id); |
|
1950 } |
|
1951 } |
|
1952 |
|
1953 struct SectionInfo { |
|
1954 std::string name; |
|
1955 std::vector<std::string> items; |
|
1956 |
|
1957 SectionInfo(const std::string& _name) : name(_name) {} |
|
1958 }; |
|
1959 |
|
1960 std::vector<SectionInfo> nodesets; |
|
1961 std::vector<SectionInfo> edgesets; |
|
1962 std::vector<SectionInfo> undiredgesets; |
|
1963 |
|
1964 std::vector<SectionInfo> nodes; |
|
1965 std::vector<SectionInfo> edges; |
|
1966 std::vector<SectionInfo> undiredges; |
|
1967 |
|
1968 std::vector<SectionInfo> attributes; |
|
1969 |
|
1970 std::vector<std::string> sections; |
|
1971 |
|
1972 std::string current; |
|
1973 |
|
1974 }; |
|
1975 |
|
1976 } |
|
1977 #endif |
|