gravatar
deba@inf.elte.hu
deba@inf.elte.hu
New skip*() functions in (Dig|G)raphReader
0 1 0
default
1 file changed with 79 insertions and 13 deletions:
↑ Collapse diff ↑
Ignore white space 768 line context
... ...
@@ -98,2303 +98,2369 @@
98 98
      virtual void set(const Item& item ,const std::string& value) {
99 99
	_map.set(item, _converter(value));
100 100
      }
101 101
    };
102 102

	
103 103
    template <typename _Graph, bool _dir, typename _Map, 
104 104
	      typename _Converter = DefaultConverter<typename _Map::Value> >
105 105
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
106 106
    public:
107 107
      typedef _Map Map;
108 108
      typedef _Converter Converter;
109 109
      typedef _Graph Graph;
110 110
      typedef typename Graph::Edge Item;
111 111
      static const bool dir = _dir;
112 112
      
113 113
    private:
114 114
      const Graph& _graph;
115 115
      Map& _map;
116 116
      Converter _converter;
117 117

	
118 118
    public:
119 119
      GraphArcMapStorage(const Graph& graph, Map& map, 
120 120
			 const Converter& converter = Converter()) 
121 121
	: _graph(graph), _map(map), _converter(converter) {}
122 122
      virtual ~GraphArcMapStorage() {}
123 123

	
124 124
      virtual void set(const Item& item ,const std::string& value) {
125 125
	_map.set(_graph.direct(item, dir), _converter(value));
126 126
      }
127 127
    };
128 128

	
129 129
    class ValueStorageBase {
130 130
    public:
131 131
      ValueStorageBase() {}
132 132
      virtual ~ValueStorageBase() {}
133 133

	
134 134
      virtual void set(const std::string&) = 0;
135 135
    };
136 136

	
137 137
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
138 138
    class ValueStorage : public ValueStorageBase {
139 139
    public:
140 140
      typedef _Value Value;
141 141
      typedef _Converter Converter;
142 142

	
143 143
    private:
144 144
      Value& _value;
145 145
      Converter _converter;
146 146

	
147 147
    public:
148 148
      ValueStorage(Value& value, const Converter& converter = Converter())
149 149
 	: _value(value), _converter(converter) {}
150 150

	
151 151
      virtual void set(const std::string& value) {
152 152
	_value = _converter(value);
153 153
      }
154 154
    };
155 155

	
156 156
    template <typename Value>
157 157
    struct MapLookUpConverter {
158 158
      const std::map<std::string, Value>& _map;
159 159

	
160 160
      MapLookUpConverter(const std::map<std::string, Value>& map)
161 161
        : _map(map) {}
162 162

	
163 163
      Value operator()(const std::string& str) {
164 164
        typename std::map<std::string, Value>::const_iterator it =
165 165
          _map.find(str);
166 166
        if (it == _map.end()) {
167 167
          std::ostringstream msg;
168 168
          msg << "Item not found: " << str;
169 169
          throw DataFormatError(msg.str().c_str());
170 170
        }
171 171
        return it->second;
172 172
      }
173 173
    };
174 174

	
175 175
    template <typename Graph>
176 176
    struct GraphArcLookUpConverter {
177 177
      const Graph& _graph;
178 178
      const std::map<std::string, typename Graph::Edge>& _map;
179 179
      
180 180
      GraphArcLookUpConverter(const Graph& graph, 
181 181
			      const std::map<std::string,
182 182
			                     typename Graph::Edge>& map) 
183 183
	: _graph(graph), _map(map) {}
184 184
      
185 185
      typename Graph::Arc operator()(const std::string& str) {
186 186
	if (str.empty() || (str[0] != '+' && str[0] != '-')) {
187 187
	  throw DataFormatError("Item must start with '+' or '-'");
188 188
	}
189 189
	typename std::map<std::string, typename Graph::Edge>
190 190
	  ::const_iterator it = _map.find(str.substr(1));
191 191
	if (it == _map.end()) {
192 192
	  throw DataFormatError("Item not found");
193 193
	}
194 194
	return _graph.direct(it->second, str[0] == '+');
195 195
      }
196 196
    };
197 197

	
198 198
    bool isWhiteSpace(char c) {
199 199
      return c == ' ' || c == '\t' || c == '\v' || 
200 200
        c == '\n' || c == '\r' || c == '\f'; 
201 201
    }
202 202
    
203 203
    bool isOct(char c) {
204 204
      return '0' <= c && c <='7'; 
205 205
    }
206 206
    
207 207
    int valueOct(char c) {
208 208
      LEMON_ASSERT(isOct(c), "The character is not octal.");
209 209
      return c - '0';
210 210
    }
211 211

	
212 212
    bool isHex(char c) {
213 213
      return ('0' <= c && c <= '9') || 
214 214
	('a' <= c && c <= 'z') || 
215 215
	('A' <= c && c <= 'Z'); 
216 216
    }
217 217
    
218 218
    int valueHex(char c) {
219 219
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
220 220
      if ('0' <= c && c <= '9') return c - '0';
221 221
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
222 222
      return c - 'A' + 10;
223 223
    }
224 224

	
225 225
    bool isIdentifierFirstChar(char c) {
226 226
      return ('a' <= c && c <= 'z') ||
227 227
	('A' <= c && c <= 'Z') || c == '_';
228 228
    }
229 229

	
230 230
    bool isIdentifierChar(char c) {
231 231
      return isIdentifierFirstChar(c) ||
232 232
	('0' <= c && c <= '9');
233 233
    }
234 234

	
235 235
    char readEscape(std::istream& is) {
236 236
      char c;
237 237
      if (!is.get(c))
238 238
	throw DataFormatError("Escape format error");
239 239

	
240 240
      switch (c) {
241 241
      case '\\':
242 242
	return '\\';
243 243
      case '\"':
244 244
	return '\"';
245 245
      case '\'':
246 246
	return '\'';
247 247
      case '\?':
248 248
	return '\?';
249 249
      case 'a':
250 250
	return '\a';
251 251
      case 'b':
252 252
	return '\b';
253 253
      case 'f':
254 254
	return '\f';
255 255
      case 'n':
256 256
	return '\n';
257 257
      case 'r':
258 258
	return '\r';
259 259
      case 't':
260 260
	return '\t';
261 261
      case 'v':
262 262
	return '\v';
263 263
      case 'x':
264 264
	{
265 265
	  int code;
266 266
	  if (!is.get(c) || !isHex(c)) 
267 267
	    throw DataFormatError("Escape format error");
268 268
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
269 269
	  else code = code * 16 + valueHex(c);
270 270
	  return code;
271 271
	}
272 272
      default:
273 273
	{
274 274
	  int code;
275 275
	  if (!isOct(c)) 
276 276
	    throw DataFormatError("Escape format error");
277 277
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
278 278
	    is.putback(c);
279 279
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
280 280
	    is.putback(c);
281 281
	  else code = code * 8 + valueOct(c);
282 282
	  return code;
283 283
	}	      
284 284
      } 
285 285
    }
286 286
    
287 287
    std::istream& readToken(std::istream& is, std::string& str) {
288 288
      std::ostringstream os;
289 289

	
290 290
      char c;
291 291
      is >> std::ws;
292 292
      
293 293
      if (!is.get(c)) 
294 294
	return is;
295 295

	
296 296
      if (c == '\"') {
297 297
	while (is.get(c) && c != '\"') {
298 298
	  if (c == '\\') 
299 299
	    c = readEscape(is);
300 300
	  os << c;
301 301
	}
302 302
	if (!is) 
303 303
	  throw DataFormatError("Quoted format error");
304 304
      } else {
305 305
	is.putback(c);
306 306
	while (is.get(c) && !isWhiteSpace(c)) {
307 307
	  if (c == '\\') 
308 308
	    c = readEscape(is);
309 309
	  os << c;
310 310
	}
311 311
	if (!is) {
312 312
	  is.clear();
313 313
	} else {
314 314
	  is.putback(c);
315 315
	}
316 316
      }
317 317
      str = os.str();
318 318
      return is;
319 319
    }
320 320

	
321 321
    class Section {
322 322
    public:
323 323
      virtual ~Section() {}
324 324
      virtual void process(std::istream& is, int& line_num) = 0;
325 325
    };
326 326

	
327 327
    template <typename Functor>
328 328
    class LineSection : public Section {
329 329
    private:
330 330

	
331 331
      Functor _functor;
332 332

	
333 333
    public:
334 334
      
335 335
      LineSection(const Functor& functor) : _functor(functor) {}
336 336
      virtual ~LineSection() {}
337 337

	
338 338
      virtual void process(std::istream& is, int& line_num) {
339 339
	char c;
340 340
	std::string line;
341 341
	while (is.get(c) && c != '@') {
342 342
	  if (c == '\n') {
343 343
	    ++line_num;
344 344
	  } else if (c == '#') {
345 345
	    getline(is, line);
346 346
	    ++line_num;
347 347
	  } else if (!isWhiteSpace(c)) {
348 348
	    is.putback(c);
349 349
	    getline(is, line);
350 350
	    _functor(line);
351 351
	    ++line_num;
352 352
	  }
353 353
	}
354 354
	if (is) is.putback(c);
355 355
	else if (is.eof()) is.clear();
356 356
      }
357 357
    };
358 358

	
359 359
    template <typename Functor>
360 360
    class StreamSection : public Section {
361 361
    private:
362 362

	
363 363
      Functor _functor;
364 364

	
365 365
    public:
366 366
      
367 367
      StreamSection(const Functor& functor) : _functor(functor) {}
368 368
      virtual ~StreamSection() {} 
369 369

	
370 370
      virtual void process(std::istream& is, int& line_num) {
371 371
	_functor(is, line_num);
372 372
	char c;
373 373
	std::string line;
374 374
	while (is.get(c) && c != '@') {
375 375
	  if (c == '\n') {
376 376
	    ++line_num;
377 377
	  } else if (!isWhiteSpace(c)) {
378 378
	    getline(is, line);
379 379
	    ++line_num;
380 380
	  }
381 381
	}
382 382
	if (is) is.putback(c);
383 383
	else if (is.eof()) is.clear();	
384 384
      }
385 385
    };
386 386
    
387 387
  }
388 388

	
389 389
  /// \ingroup lemon_io
390 390
  ///  
391 391
  /// \brief LGF reader for directed graphs
392 392
  ///
393 393
  /// This utility reads an \ref lgf-format "LGF" file.
394 394
  ///
395 395
  /// The reading method does a batch processing. The user creates a
396 396
  /// reader object, then various reading rules can be added to the
397 397
  /// reader, and eventually the reading is executed with the \c run()
398 398
  /// member function. A map reading rule can be added to the reader
399 399
  /// with the \c nodeMap() or \c arcMap() members. An optional
400 400
  /// converter parameter can also be added as a standard functor
401 401
  /// converting from std::string to the value type of the map. If it
402 402
  /// is set, it will determine how the tokens in the file should be
403 403
  /// is converted to the map's value type. If the functor is not set,
404 404
  /// then a default conversion will be used. One map can be read into
405 405
  /// multiple map objects at the same time. The \c attribute(), \c
406 406
  /// node() and \c arc() functions are used to add attribute reading
407 407
  /// rules.
408 408
  ///
409 409
  ///\code
410 410
  ///     DigraphReader<Digraph>(std::cin, digraph).
411 411
  ///       nodeMap("coordinates", coord_map).
412 412
  ///       arcMap("capacity", cap_map).
413 413
  ///       node("source", src).
414 414
  ///       node("target", trg).
415 415
  ///       attribute("caption", caption).
416 416
  ///       run();
417 417
  ///\endcode
418 418
  ///
419 419
  /// By default the reader uses the first section in the file of the
420 420
  /// proper type. If a section has an optional name, then it can be
421 421
  /// selected for reading by giving an optional name parameter to the
422 422
  /// \c nodes(), \c arcs() or \c attributes() functions. The readers
423 423
  /// also can load extra sections with the \c sectionLines() and
424 424
  /// sectionStream() functions.
425 425
  ///
426 426
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
427 427
  /// that the nodes or arcs should not be constructed (added to the
428 428
  /// graph) during the reading, but instead the label map of the items
429 429
  /// are given as a parameter of these functions. An
430 430
  /// application of these function is multipass reading, which is
431 431
  /// important if two \e \@arcs sections must be read from the
432 432
  /// file. In this example the first phase would read the node set and one
433 433
  /// of the arc sets, while the second phase would read the second arc
434 434
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
435 435
  /// The previously read label node map should be passed to the \c
436 436
  /// useNodes() functions. Another application of multipass reading when
437 437
  /// paths are given as a node map or an arc map. It is impossible read this in
438 438
  /// a single pass, because the arcs are not constructed when the node
439 439
  /// maps are read.
440 440
  template <typename _Digraph>
441 441
  class DigraphReader {
442 442
  public:
443 443

	
444 444
    typedef _Digraph Digraph;
445 445
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
446 446
    
447 447
  private:
448 448

	
449 449

	
450 450
    std::istream* _is;
451 451
    bool local_is;
452 452

	
453 453
    Digraph& _digraph;
454 454

	
455 455
    std::string _nodes_caption;
456 456
    std::string _arcs_caption;
457 457
    std::string _attributes_caption;
458 458

	
459 459
    typedef std::map<std::string, Node> NodeIndex;
460 460
    NodeIndex _node_index;
461 461
    typedef std::map<std::string, Arc> ArcIndex;
462 462
    ArcIndex _arc_index;
463 463
    
464 464
    typedef std::vector<std::pair<std::string, 
465 465
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
466 466
    NodeMaps _node_maps; 
467 467

	
468 468
    typedef std::vector<std::pair<std::string,
469 469
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
470 470
    ArcMaps _arc_maps;
471 471

	
472 472
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
473 473
      Attributes;
474 474
    Attributes _attributes;
475 475

	
476 476
    typedef std::map<std::string, _reader_bits::Section*> Sections;
477 477
    Sections _sections;
478 478

	
479 479
    bool _use_nodes;
480 480
    bool _use_arcs;
481 481

	
482
    bool _skip_nodes;
483
    bool _skip_arcs;
484

	
482 485
    int line_num;
483 486
    std::istringstream line;
484 487

	
485 488
  public:
486 489

	
487 490
    /// \brief Constructor
488 491
    ///
489 492
    /// Construct a directed graph reader, which reads from the given
490 493
    /// input stream.
491 494
    DigraphReader(std::istream& is, Digraph& digraph) 
492 495
      : _is(&is), local_is(false), _digraph(digraph),
493
	_use_nodes(false), _use_arcs(false) {}
496
	_use_nodes(false), _use_arcs(false),
497
	_skip_nodes(false), _skip_arcs(false) {}
494 498

	
495 499
    /// \brief Constructor
496 500
    ///
497 501
    /// Construct a directed graph reader, which reads from the given
498 502
    /// file.
499 503
    DigraphReader(const std::string& fn, Digraph& digraph) 
500 504
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
501
    	_use_nodes(false), _use_arcs(false) {}
505
    	_use_nodes(false), _use_arcs(false),
506
	_skip_nodes(false), _skip_arcs(false) {}
502 507
    
503 508
    /// \brief Constructor
504 509
    ///
505 510
    /// Construct a directed graph reader, which reads from the given
506 511
    /// file.
507 512
    DigraphReader(const char* fn, Digraph& digraph) 
508 513
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
509
    	_use_nodes(false), _use_arcs(false) {}
514
    	_use_nodes(false), _use_arcs(false),
515
	_skip_nodes(false), _skip_arcs(false) {}
510 516

	
511 517
    /// \brief Copy constructor
512 518
    ///
513 519
    /// The copy constructor transfers all data from the other reader,
514 520
    /// therefore the copied reader will not be usable more. 
515 521
    DigraphReader(DigraphReader& other) 
516 522
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
517
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) {
523
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
524
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
518 525

	
519 526
      other._is = 0;
520 527
      other.local_is = false;
521 528
      
522 529
      _node_index.swap(other._node_index);
523 530
      _arc_index.swap(other._arc_index);
524 531

	
525 532
      _node_maps.swap(other._node_maps);
526 533
      _arc_maps.swap(other._arc_maps);
527 534
      _attributes.swap(other._attributes);
528 535

	
529 536
      _nodes_caption = other._nodes_caption;
530 537
      _arcs_caption = other._arcs_caption;
531 538
      _attributes_caption = other._attributes_caption;
532 539

	
533 540
      _sections.swap(other._sections);
534 541
    }
535 542

	
536 543
    /// \brief Destructor
537 544
    ~DigraphReader() {
538 545
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
539 546
	   it != _node_maps.end(); ++it) {
540 547
	delete it->second;
541 548
      }
542 549

	
543 550
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
544 551
	   it != _arc_maps.end(); ++it) {
545 552
	delete it->second;
546 553
      }
547 554

	
548 555
      for (typename Attributes::iterator it = _attributes.begin(); 
549 556
	   it != _attributes.end(); ++it) {
550 557
	delete it->second;
551 558
      }
552 559

	
553 560
      for (typename Sections::iterator it = _sections.begin(); 
554 561
	   it != _sections.end(); ++it) {
555 562
	delete it->second;
556 563
      }
557 564

	
558 565
      if (local_is) {
559 566
	delete _is;
560 567
      }
561 568

	
562 569
    }
563 570

	
564 571
  private:
565 572
    
566 573
    DigraphReader& operator=(const DigraphReader&);
567 574

	
568 575
  public:
569 576

	
570 577
    /// \name Reading rules
571 578
    /// @{
572 579
    
573 580
    /// \brief Node map reading rule
574 581
    ///
575 582
    /// Add a node map reading rule to the reader.
576 583
    template <typename Map>
577 584
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
578 585
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
579 586
      _reader_bits::MapStorageBase<Node>* storage = 
580 587
	new _reader_bits::MapStorage<Node, Map>(map);
581 588
      _node_maps.push_back(std::make_pair(caption, storage));
582 589
      return *this;
583 590
    }
584 591

	
585 592
    /// \brief Node map reading rule
586 593
    ///
587 594
    /// Add a node map reading rule with specialized converter to the
588 595
    /// reader.
589 596
    template <typename Map, typename Converter>
590 597
    DigraphReader& nodeMap(const std::string& caption, Map& map, 
591 598
			   const Converter& converter = Converter()) {
592 599
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
593 600
      _reader_bits::MapStorageBase<Node>* storage = 
594 601
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
595 602
      _node_maps.push_back(std::make_pair(caption, storage));
596 603
      return *this;
597 604
    }
598 605

	
599 606
    /// \brief Arc map reading rule
600 607
    ///
601 608
    /// Add an arc map reading rule to the reader.
602 609
    template <typename Map>
603 610
    DigraphReader& arcMap(const std::string& caption, Map& map) {
604 611
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
605 612
      _reader_bits::MapStorageBase<Arc>* storage = 
606 613
	new _reader_bits::MapStorage<Arc, Map>(map);
607 614
      _arc_maps.push_back(std::make_pair(caption, storage));
608 615
      return *this;
609 616
    }
610 617

	
611 618
    /// \brief Arc map reading rule
612 619
    ///
613 620
    /// Add an arc map reading rule with specialized converter to the
614 621
    /// reader.
615 622
    template <typename Map, typename Converter>
616 623
    DigraphReader& arcMap(const std::string& caption, Map& map, 
617 624
			  const Converter& converter = Converter()) {
618 625
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
619 626
      _reader_bits::MapStorageBase<Arc>* storage = 
620 627
	new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
621 628
      _arc_maps.push_back(std::make_pair(caption, storage));
622 629
      return *this;
623 630
    }
624 631

	
625 632
    /// \brief Attribute reading rule
626 633
    ///
627 634
    /// Add an attribute reading rule to the reader.
628 635
    template <typename Value>
629 636
    DigraphReader& attribute(const std::string& caption, Value& value) {
630 637
      _reader_bits::ValueStorageBase* storage = 
631 638
	new _reader_bits::ValueStorage<Value>(value);
632 639
      _attributes.insert(std::make_pair(caption, storage));
633 640
      return *this;
634 641
    }
635 642

	
636 643
    /// \brief Attribute reading rule
637 644
    ///
638 645
    /// Add an attribute reading rule with specialized converter to the
639 646
    /// reader.
640 647
    template <typename Value, typename Converter>
641 648
    DigraphReader& attribute(const std::string& caption, Value& value, 
642 649
			     const Converter& converter = Converter()) {
643 650
      _reader_bits::ValueStorageBase* storage = 
644 651
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
645 652
      _attributes.insert(std::make_pair(caption, storage));
646 653
      return *this;
647 654
    }
648 655

	
649 656
    /// \brief Node reading rule
650 657
    ///
651 658
    /// Add a node reading rule to reader.
652 659
    DigraphReader& node(const std::string& caption, Node& node) {
653 660
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
654 661
      Converter converter(_node_index);
655 662
      _reader_bits::ValueStorageBase* storage = 
656 663
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
657 664
      _attributes.insert(std::make_pair(caption, storage));
658 665
      return *this;
659 666
    }
660 667

	
661 668
    /// \brief Arc reading rule
662 669
    ///
663 670
    /// Add an arc reading rule to reader.
664 671
    DigraphReader& arc(const std::string& caption, Arc& arc) {
665 672
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
666 673
      Converter converter(_arc_index);
667 674
      _reader_bits::ValueStorageBase* storage = 
668 675
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
669 676
      _attributes.insert(std::make_pair(caption, storage));
670 677
      return *this;
671 678
    }
672 679

	
673 680
    /// @}
674 681

	
675 682
    /// \name Select section by name
676 683
    /// @{
677 684

	
678 685
    /// \brief Set \c \@nodes section to be read
679 686
    ///
680 687
    /// Set \c \@nodes section to be read
681 688
    DigraphReader& nodes(const std::string& caption) {
682 689
      _nodes_caption = caption;
683 690
      return *this;
684 691
    }
685 692

	
686 693
    /// \brief Set \c \@arcs section to be read
687 694
    ///
688 695
    /// Set \c \@arcs section to be read
689 696
    DigraphReader& arcs(const std::string& caption) {
690 697
      _arcs_caption = caption;
691 698
      return *this;
692 699
    }
693 700

	
694 701
    /// \brief Set \c \@attributes section to be read
695 702
    ///
696 703
    /// Set \c \@attributes section to be read
697 704
    DigraphReader& attributes(const std::string& caption) {
698 705
      _attributes_caption = caption;
699 706
      return *this;
700 707
    }
701 708

	
702 709
    /// @}
703 710

	
704 711
    /// \name Section readers
705 712
    /// @{
706 713

	
707 714
    /// \brief Add a section processor with line oriented reading
708 715
    ///
709 716
    /// In the \e LGF file extra sections can be placed, which contain
710 717
    /// any data in arbitrary format. These sections can be read with
711 718
    /// this function line by line. The first parameter is the type
712 719
    /// descriptor of the section, the second is a functor, which
713 720
    /// takes just one \c std::string parameter. At the reading
714 721
    /// process, each line of the section will be given to the functor
715 722
    /// object. However, the empty lines and the comment lines are
716 723
    /// filtered out, and the leading whitespaces are stipped from
717 724
    /// each processed string.
718 725
    ///
719 726
    /// For example let's see a section, which contain several
720 727
    /// integers, which should be inserted into a vector.
721 728
    ///\code
722 729
    ///  @numbers
723 730
    ///  12 45 23
724 731
    ///  4
725 732
    ///  23 6
726 733
    ///\endcode
727 734
    ///
728 735
    /// The functor is implemented as an struct:
729 736
    ///\code
730 737
    ///  struct NumberSection {
731 738
    ///    std::vector<int>& _data;
732 739
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
733 740
    ///    void operator()(const std::string& line) {
734 741
    ///      std::istringstream ls(line);
735 742
    ///      int value;
736 743
    ///      while (ls >> value) _data.push_back(value);
737 744
    ///    }
738 745
    ///  };
739 746
    ///
740 747
    ///  // ...
741 748
    ///
742 749
    ///  reader.sectionLines("numbers", NumberSection(vec));  
743 750
    ///\endcode
744 751
    template <typename Functor>
745 752
    DigraphReader& sectionLines(const std::string& type, Functor functor) {
746 753
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
747 754
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
748 755
		   "Multiple reading of section.");
749 756
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
750 757
		   type != "attributes", "Multiple reading of section.");
751 758
      _sections.insert(std::make_pair(type, 
752 759
        new _reader_bits::LineSection<Functor>(functor)));
753 760
      return *this;
754 761
    }
755 762

	
756 763

	
757 764
    /// \brief Add a section processor with stream oriented reading
758 765
    ///
759 766
    /// In the \e LGF file extra sections can be placed, which contain
760 767
    /// any data in arbitrary format. These sections can be read
761 768
    /// directly with this function. The first parameter is the type
762 769
    /// of the section, the second is a functor, which takes an \c
763 770
    /// std::istream& and an int& parameter, the latter regard to the
764 771
    /// line number of stream. The functor can read the input while
765 772
    /// the section go on, and the line number should be modified
766 773
    /// accordingly.
767 774
    template <typename Functor>
768 775
    DigraphReader& sectionStream(const std::string& type, Functor functor) {
769 776
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
770 777
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
771 778
		   "Multiple reading of section.");
772 779
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
773 780
		   type != "attributes", "Multiple reading of section.");
774 781
      _sections.insert(std::make_pair(type, 
775 782
	 new _reader_bits::StreamSection<Functor>(functor)));
776 783
      return *this;
777 784
    }    
778 785
    
779 786
    /// @}
780 787

	
781 788
    /// \name Using previously constructed node or arc set
782 789
    /// @{
783 790

	
784 791
    /// \brief Use previously constructed node set
785 792
    ///
786 793
    /// Use previously constructed node set, and specify the node
787 794
    /// label map.
788 795
    template <typename Map>
789 796
    DigraphReader& useNodes(const Map& map) {
790 797
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
791 798
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
792 799
      _use_nodes = true;
793 800
      _writer_bits::DefaultConverter<typename Map::Value> converter;
794 801
      for (NodeIt n(_digraph); n != INVALID; ++n) {
795 802
	_node_index.insert(std::make_pair(converter(map[n]), n));
796 803
      }
797 804
      return *this;
798 805
    }
799 806

	
800 807
    /// \brief Use previously constructed node set
801 808
    ///
802 809
    /// Use previously constructed node set, and specify the node
803 810
    /// label map and a functor which converts the label map values to
804 811
    /// std::string.
805 812
    template <typename Map, typename Converter>
806 813
    DigraphReader& useNodes(const Map& map, 
807 814
			    const Converter& converter = Converter()) {
808 815
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
809 816
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
810 817
      _use_nodes = true;
811 818
      for (NodeIt n(_digraph); n != INVALID; ++n) {
812 819
	_node_index.insert(std::make_pair(converter(map[n]), n));
813 820
      }
814 821
      return *this;
815 822
    }
816 823

	
817 824
    /// \brief Use previously constructed arc set
818 825
    ///
819 826
    /// Use previously constructed arc set, and specify the arc
820 827
    /// label map.
821 828
    template <typename Map>
822 829
    DigraphReader& useArcs(const Map& map) {
823 830
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
824 831
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
825 832
      _use_arcs = true;
826 833
      _writer_bits::DefaultConverter<typename Map::Value> converter;
827 834
      for (ArcIt a(_digraph); a != INVALID; ++a) {
828 835
	_arc_index.insert(std::make_pair(converter(map[a]), a));
829 836
      }
830 837
      return *this;
831 838
    }
832 839

	
833 840
    /// \brief Use previously constructed arc set
834 841
    ///
835 842
    /// Use previously constructed arc set, and specify the arc
836 843
    /// label map and a functor which converts the label map values to
837 844
    /// std::string.
838 845
    template <typename Map, typename Converter>
839 846
    DigraphReader& useArcs(const Map& map, 
840
			    const Converter& converter = Converter()) {
847
			   const Converter& converter = Converter()) {
841 848
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
842 849
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
843 850
      _use_arcs = true;
844 851
      for (ArcIt a(_digraph); a != INVALID; ++a) {
845 852
	_arc_index.insert(std::make_pair(converter(map[a]), a));
846 853
      }
847 854
      return *this;
848 855
    }
849 856

	
857
    /// \brief Skips the reading of node section
858
    ///
859
    /// Omit the reading of the node section. This implies that each node
860
    /// map reading rule will be abanoned, and the nodes of the graph
861
    /// will not be constructed, which usually cause that the arc set
862
    /// could not be read due to lack of node name
863
    /// resolving. Therefore, the \c skipArcs() should be used too, or
864
    /// the useNodes() member function should be used to specify the
865
    /// label of the nodes.
866
    DigraphReader& skipNodes() {
867
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
868
      _skip_nodes = true;
869
      return *this;
870
    }
871

	
872
    /// \brief Skips the reading of arc section
873
    ///
874
    /// Omit the reading of the arc section. This implies that each arc
875
    /// map reading rule will be abanoned, and the arcs of the graph
876
    /// will not be constructed.
877
    DigraphReader& skipArcs() {
878
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set"); 
879
      _skip_arcs = true;
880
      return *this;
881
    }
882

	
850 883
    /// @}
851 884

	
852 885
  private:
853 886

	
854 887
    bool readLine() {
855 888
      std::string str;
856 889
      while(++line_num, std::getline(*_is, str)) {
857 890
	line.clear(); line.str(str);
858 891
	char c;
859 892
	if (line >> std::ws >> c && c != '#') {
860 893
	  line.putback(c);
861 894
	  return true;
862 895
	}
863 896
      }
864 897
      return false;
865 898
    }
866 899

	
867 900
    bool readSuccess() {
868 901
      return static_cast<bool>(*_is);
869 902
    }
870 903
    
871 904
    void skipSection() {
872 905
      char c;
873 906
      while (readSuccess() && line >> c && c != '@') {
874 907
	readLine();
875 908
      }
876 909
      line.putback(c);
877 910
    }
878 911

	
879 912
    void readNodes() {
880 913

	
881 914
      std::vector<int> map_index(_node_maps.size());
882 915
      int map_num, label_index;
883 916

	
884 917
      char c;
885 918
      if (!readLine() || !(line >> c) || c == '@') {
886 919
	if (readSuccess() && line) line.putback(c);
887 920
	if (!_node_maps.empty()) 
888 921
	  throw DataFormatError("Cannot find map names");
889 922
	return;
890 923
      }
891 924
      line.putback(c);
892 925

	
893 926
      {
894 927
	std::map<std::string, int> maps;
895 928
	
896 929
	std::string map;
897 930
	int index = 0;
898 931
	while (_reader_bits::readToken(line, map)) {
899 932
	  if (maps.find(map) != maps.end()) {
900 933
	    std::ostringstream msg;
901 934
	    msg << "Multiple occurence of node map: " << map;
902 935
	    throw DataFormatError(msg.str().c_str());
903 936
	  }
904 937
	  maps.insert(std::make_pair(map, index));
905 938
	  ++index;
906 939
	}
907 940
	
908 941
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
909 942
	  std::map<std::string, int>::iterator jt = 
910 943
	    maps.find(_node_maps[i].first);
911 944
	  if (jt == maps.end()) {
912 945
	    std::ostringstream msg;
913 946
	    msg << "Map not found in file: " << _node_maps[i].first;
914 947
	    throw DataFormatError(msg.str().c_str());
915 948
	  }
916 949
	  map_index[i] = jt->second;
917 950
	}
918 951

	
919 952
	{
920 953
	  std::map<std::string, int>::iterator jt = maps.find("label");
921 954
	  if (jt != maps.end()) {
922 955
	    label_index = jt->second;
923 956
	  } else {
924 957
	    label_index = -1;
925 958
	  }
926 959
	}
927 960
	map_num = maps.size();
928 961
      }
929 962

	
930 963
      while (readLine() && line >> c && c != '@') {
931 964
	line.putback(c);
932 965

	
933 966
	std::vector<std::string> tokens(map_num);
934 967
	for (int i = 0; i < map_num; ++i) {
935 968
	  if (!_reader_bits::readToken(line, tokens[i])) {
936 969
	    std::ostringstream msg;
937 970
	    msg << "Column not found (" << i + 1 << ")";
938 971
	    throw DataFormatError(msg.str().c_str());
939 972
	  }
940 973
	}
941 974
	if (line >> std::ws >> c)
942 975
	  throw DataFormatError("Extra character on the end of line");
943 976
	
944 977
	Node n;
945 978
	if (!_use_nodes) {
946 979
	  n = _digraph.addNode();
947 980
	  if (label_index != -1)
948 981
	    _node_index.insert(std::make_pair(tokens[label_index], n));
949 982
	} else {
950 983
	  if (label_index == -1) 
951 984
	    throw DataFormatError("Label map not found in file");
952 985
	  typename std::map<std::string, Node>::iterator it =
953 986
	    _node_index.find(tokens[label_index]);
954 987
	  if (it == _node_index.end()) {
955 988
	    std::ostringstream msg;
956 989
	    msg << "Node with label not found: " << tokens[label_index];
957 990
	    throw DataFormatError(msg.str().c_str());	    
958 991
	  }
959 992
	  n = it->second;
960 993
	}
961 994

	
962 995
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
963 996
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
964 997
	}
965 998

	
966 999
      }
967 1000
      if (readSuccess()) {
968 1001
	line.putback(c);
969 1002
      }
970 1003
    }
971 1004

	
972 1005
    void readArcs() {
973 1006

	
974 1007
      std::vector<int> map_index(_arc_maps.size());
975 1008
      int map_num, label_index;
976 1009

	
977 1010
      char c;
978 1011
      if (!readLine() || !(line >> c) || c == '@') {
979 1012
	if (readSuccess() && line) line.putback(c);
980 1013
	if (!_arc_maps.empty()) 
981 1014
	  throw DataFormatError("Cannot find map names");
982 1015
	return;
983 1016
      }
984 1017
      line.putback(c);
985 1018
      
986 1019
      {
987 1020
	std::map<std::string, int> maps;
988 1021
	
989 1022
	std::string map;
990 1023
	int index = 0;
991 1024
	while (_reader_bits::readToken(line, map)) {
992 1025
	  if (maps.find(map) != maps.end()) {
993 1026
	    std::ostringstream msg;
994 1027
	    msg << "Multiple occurence of arc map: " << map;
995 1028
	    throw DataFormatError(msg.str().c_str());
996 1029
	  }
997 1030
	  maps.insert(std::make_pair(map, index));
998 1031
	  ++index;
999 1032
	}
1000 1033
	
1001 1034
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1002 1035
	  std::map<std::string, int>::iterator jt = 
1003 1036
	    maps.find(_arc_maps[i].first);
1004 1037
	  if (jt == maps.end()) {
1005 1038
	    std::ostringstream msg;
1006 1039
	    msg << "Map not found in file: " << _arc_maps[i].first;
1007 1040
	    throw DataFormatError(msg.str().c_str());
1008 1041
	  }
1009 1042
	  map_index[i] = jt->second;
1010 1043
	}
1011 1044

	
1012 1045
	{
1013 1046
	  std::map<std::string, int>::iterator jt = maps.find("label");
1014 1047
	  if (jt != maps.end()) {
1015 1048
	    label_index = jt->second;
1016 1049
	  } else {
1017 1050
	    label_index = -1;
1018 1051
	  }
1019 1052
	}
1020 1053
	map_num = maps.size();
1021 1054
      }
1022 1055

	
1023 1056
      while (readLine() && line >> c && c != '@') {
1024 1057
	line.putback(c);
1025 1058

	
1026 1059
	std::string source_token;
1027 1060
	std::string target_token;
1028 1061

	
1029 1062
	if (!_reader_bits::readToken(line, source_token))
1030 1063
	  throw DataFormatError("Source not found");
1031 1064

	
1032 1065
	if (!_reader_bits::readToken(line, target_token))
1033 1066
	  throw DataFormatError("Target not found");
1034 1067
	
1035 1068
	std::vector<std::string> tokens(map_num);
1036 1069
	for (int i = 0; i < map_num; ++i) {
1037 1070
	  if (!_reader_bits::readToken(line, tokens[i])) {
1038 1071
	    std::ostringstream msg;
1039 1072
	    msg << "Column not found (" << i + 1 << ")";
1040 1073
	    throw DataFormatError(msg.str().c_str());
1041 1074
	  }
1042 1075
	}
1043 1076
	if (line >> std::ws >> c)
1044 1077
	  throw DataFormatError("Extra character on the end of line");
1045 1078
	
1046 1079
	Arc a;
1047 1080
	if (!_use_arcs) {
1048 1081

	
1049 1082
          typename NodeIndex::iterator it;
1050 1083
 
1051 1084
          it = _node_index.find(source_token);
1052 1085
          if (it == _node_index.end()) {
1053 1086
            std::ostringstream msg;
1054 1087
            msg << "Item not found: " << source_token;
1055 1088
            throw DataFormatError(msg.str().c_str());
1056 1089
          }
1057 1090
          Node source = it->second;
1058 1091

	
1059 1092
          it = _node_index.find(target_token);
1060 1093
          if (it == _node_index.end()) {       
1061 1094
            std::ostringstream msg;            
1062 1095
            msg << "Item not found: " << target_token;
1063 1096
            throw DataFormatError(msg.str().c_str());
1064 1097
          }                                          
1065 1098
          Node target = it->second;                            
1066 1099

	
1067 1100
	  a = _digraph.addArc(source, target);
1068 1101
	  if (label_index != -1) 
1069 1102
	    _arc_index.insert(std::make_pair(tokens[label_index], a));
1070 1103
	} else {
1071 1104
	  if (label_index == -1) 
1072 1105
	    throw DataFormatError("Label map not found in file");
1073 1106
	  typename std::map<std::string, Arc>::iterator it =
1074 1107
	    _arc_index.find(tokens[label_index]);
1075 1108
	  if (it == _arc_index.end()) {
1076 1109
	    std::ostringstream msg;
1077 1110
	    msg << "Arc with label not found: " << tokens[label_index];
1078 1111
	    throw DataFormatError(msg.str().c_str());	    
1079 1112
	  }
1080 1113
	  a = it->second;
1081 1114
	}
1082 1115

	
1083 1116
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1084 1117
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
1085 1118
	}
1086 1119

	
1087 1120
      }
1088 1121
      if (readSuccess()) {
1089 1122
	line.putback(c);
1090 1123
      }
1091 1124
    }
1092 1125

	
1093 1126
    void readAttributes() {
1094 1127

	
1095 1128
      std::set<std::string> read_attr;
1096 1129

	
1097 1130
      char c;
1098 1131
      while (readLine() && line >> c && c != '@') {
1099 1132
	line.putback(c);
1100 1133
	
1101 1134
	std::string attr, token;
1102 1135
	if (!_reader_bits::readToken(line, attr))
1103 1136
	  throw DataFormatError("Attribute name not found");
1104 1137
	if (!_reader_bits::readToken(line, token))
1105 1138
	  throw DataFormatError("Attribute value not found");
1106 1139
	if (line >> c)
1107 1140
	  throw DataFormatError("Extra character on the end of line");	  
1108 1141

	
1109 1142
	{
1110 1143
	  std::set<std::string>::iterator it = read_attr.find(attr);
1111 1144
	  if (it != read_attr.end()) {
1112 1145
	    std::ostringstream msg;
1113 1146
	    msg << "Multiple occurence of attribute " << attr;
1114 1147
	    throw DataFormatError(msg.str().c_str());
1115 1148
	  }
1116 1149
	  read_attr.insert(attr);
1117 1150
	}
1118 1151
	
1119 1152
	{
1120 1153
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1121 1154
	  while (it != _attributes.end() && it->first == attr) {
1122 1155
	    it->second->set(token);
1123 1156
	    ++it;
1124 1157
	  }
1125 1158
	}
1126 1159

	
1127 1160
      }
1128 1161
      if (readSuccess()) {
1129 1162
	line.putback(c);
1130 1163
      }
1131 1164
      for (typename Attributes::iterator it = _attributes.begin();
1132 1165
	   it != _attributes.end(); ++it) {
1133 1166
	if (read_attr.find(it->first) == read_attr.end()) {
1134 1167
	  std::ostringstream msg;
1135 1168
	  msg << "Attribute not found in file: " << it->first;
1136 1169
	  throw DataFormatError(msg.str().c_str());
1137 1170
	}	
1138 1171
      }
1139 1172
    }
1140 1173

	
1141 1174
  public:
1142 1175

	
1143 1176
    /// \name Execution of the reader    
1144 1177
    /// @{
1145 1178

	
1146 1179
    /// \brief Start the batch processing
1147 1180
    ///
1148 1181
    /// This function starts the batch processing
1149 1182
    void run() {
1150 1183
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1151 1184
      if (!*_is) {
1152 1185
	throw DataFormatError("Cannot find file");
1153 1186
      }
1154 1187
      
1155
      bool nodes_done = false;
1156
      bool arcs_done = false;
1188
      bool nodes_done = _skip_nodes;
1189
      bool arcs_done = _skip_arcs;
1157 1190
      bool attributes_done = false;
1158 1191
      std::set<std::string> extra_sections;
1159 1192

	
1160 1193
      line_num = 0;      
1161 1194
      readLine();
1162 1195
      skipSection();
1163 1196

	
1164 1197
      while (readSuccess()) {
1165 1198
	try {
1166 1199
	  char c;
1167 1200
	  std::string section, caption;
1168 1201
	  line >> c;
1169 1202
	  _reader_bits::readToken(line, section);
1170 1203
	  _reader_bits::readToken(line, caption);
1171 1204

	
1172 1205
	  if (line >> c) 
1173 1206
	    throw DataFormatError("Extra character on the end of line");
1174 1207

	
1175 1208
	  if (section == "nodes" && !nodes_done) {
1176 1209
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1177 1210
	      readNodes();
1178 1211
	      nodes_done = true;
1179 1212
	    }
1180 1213
	  } else if ((section == "arcs" || section == "edges") && 
1181 1214
		     !arcs_done) {
1182 1215
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
1183 1216
	      readArcs();
1184 1217
	      arcs_done = true;
1185 1218
	    }
1186 1219
	  } else if (section == "attributes" && !attributes_done) {
1187 1220
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1188 1221
	      readAttributes();
1189 1222
	      attributes_done = true;
1190 1223
	    }
1191 1224
	  } else {
1192 1225
	    if (extra_sections.find(section) != extra_sections.end()) {
1193 1226
	      std::ostringstream msg;
1194 1227
	      msg << "Multiple occurence of section " << section;
1195 1228
	      throw DataFormatError(msg.str().c_str());
1196 1229
	    }
1197 1230
	    Sections::iterator it = _sections.find(section);
1198 1231
	    if (it != _sections.end()) {
1199 1232
	      extra_sections.insert(section);
1200 1233
	      it->second->process(*_is, line_num);
1201 1234
	    }
1202 1235
	    readLine();
1203 1236
	    skipSection();
1204 1237
	  }
1205 1238
	} catch (DataFormatError& error) {
1206 1239
	  error.line(line_num);
1207 1240
	  throw;
1208 1241
	}	
1209 1242
      }
1210 1243

	
1211 1244
      if (!nodes_done) {
1212 1245
	throw DataFormatError("Section @nodes not found");
1213 1246
      }
1214 1247

	
1215 1248
      if (!arcs_done) {
1216 1249
	throw DataFormatError("Section @arcs not found");
1217 1250
      }
1218 1251

	
1219 1252
      if (!attributes_done && !_attributes.empty()) {
1220 1253
	throw DataFormatError("Section @attributes not found");
1221 1254
      }
1222 1255

	
1223 1256
    }
1224 1257

	
1225 1258
    /// @}
1226 1259
    
1227 1260
  };
1228 1261

	
1229 1262
  /// \relates DigraphReader
1230 1263
  template <typename Digraph>
1231 1264
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1232 1265
    DigraphReader<Digraph> tmp(is, digraph);
1233 1266
    return tmp;
1234 1267
  }
1235 1268

	
1236 1269
  /// \relates DigraphReader
1237 1270
  template <typename Digraph>
1238 1271
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
1239 1272
				       Digraph& digraph) {
1240 1273
    DigraphReader<Digraph> tmp(fn, digraph);
1241 1274
    return tmp;
1242 1275
  }
1243 1276

	
1244 1277
  /// \relates DigraphReader
1245 1278
  template <typename Digraph>
1246 1279
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1247 1280
    DigraphReader<Digraph> tmp(fn, digraph);
1248 1281
    return tmp;
1249 1282
  }
1250 1283

	
1251 1284
  /// \ingroup lemon_io
1252 1285
  ///  
1253 1286
  /// \brief LGF reader for undirected graphs
1254 1287
  ///
1255 1288
  /// This utility reads an \ref lgf-format "LGF" file.
1256 1289
  template <typename _Graph>
1257 1290
  class GraphReader {
1258 1291
  public:
1259 1292

	
1260 1293
    typedef _Graph Graph;
1261 1294
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1262 1295
    
1263 1296
  private:
1264 1297

	
1265 1298

	
1266 1299
    std::istream* _is;
1267 1300
    bool local_is;
1268 1301

	
1269 1302
    Graph& _graph;
1270 1303

	
1271 1304
    std::string _nodes_caption;
1272 1305
    std::string _edges_caption;
1273 1306
    std::string _attributes_caption;
1274 1307

	
1275 1308
    typedef std::map<std::string, Node> NodeIndex;
1276 1309
    NodeIndex _node_index;
1277 1310
    typedef std::map<std::string, Edge> EdgeIndex;
1278 1311
    EdgeIndex _edge_index;
1279 1312
    
1280 1313
    typedef std::vector<std::pair<std::string, 
1281 1314
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1282 1315
    NodeMaps _node_maps; 
1283 1316

	
1284 1317
    typedef std::vector<std::pair<std::string,
1285 1318
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1286 1319
    EdgeMaps _edge_maps;
1287 1320

	
1288 1321
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1289 1322
      Attributes;
1290 1323
    Attributes _attributes;
1291 1324

	
1292 1325
    typedef std::map<std::string, _reader_bits::Section*> Sections;
1293 1326
    Sections _sections;
1294 1327

	
1295 1328
    bool _use_nodes;
1296 1329
    bool _use_edges;
1297 1330

	
1331
    bool _skip_nodes;
1332
    bool _skip_edges;
1333

	
1298 1334
    int line_num;
1299 1335
    std::istringstream line;
1300 1336

	
1301 1337
  public:
1302 1338

	
1303 1339
    /// \brief Constructor
1304 1340
    ///
1305 1341
    /// Construct a undirected graph reader, which reads from the given
1306 1342
    /// input stream.
1307 1343
    GraphReader(std::istream& is, Graph& graph) 
1308 1344
      : _is(&is), local_is(false), _graph(graph),
1309
	_use_nodes(false), _use_edges(false) {}
1345
	_use_nodes(false), _use_edges(false),
1346
	_skip_nodes(false), _skip_edges(false) {}
1310 1347

	
1311 1348
    /// \brief Constructor
1312 1349
    ///
1313 1350
    /// Construct a undirected graph reader, which reads from the given
1314 1351
    /// file.
1315 1352
    GraphReader(const std::string& fn, Graph& graph) 
1316 1353
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1317
    	_use_nodes(false), _use_edges(false) {}
1354
    	_use_nodes(false), _use_edges(false),
1355
	_skip_nodes(false), _skip_edges(false) {}
1318 1356
    
1319 1357
    /// \brief Constructor
1320 1358
    ///
1321 1359
    /// Construct a undirected graph reader, which reads from the given
1322 1360
    /// file.
1323 1361
    GraphReader(const char* fn, Graph& graph) 
1324 1362
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1325
    	_use_nodes(false), _use_edges(false) {}
1363
    	_use_nodes(false), _use_edges(false),
1364
	_skip_nodes(false), _skip_edges(false) {}
1326 1365

	
1327 1366
    /// \brief Copy constructor
1328 1367
    ///
1329 1368
    /// The copy constructor transfers all data from the other reader,
1330 1369
    /// therefore the copied reader will not be usable more. 
1331 1370
    GraphReader(GraphReader& other) 
1332 1371
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1333
	_use_nodes(other._use_nodes), _use_edges(other._use_edges) {
1372
	_use_nodes(other._use_nodes), _use_edges(other._use_edges),
1373
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1334 1374

	
1335 1375
      other._is = 0;
1336 1376
      other.local_is = false;
1337 1377
      
1338 1378
      _node_index.swap(other._node_index);
1339 1379
      _edge_index.swap(other._edge_index);
1340 1380

	
1341 1381
      _node_maps.swap(other._node_maps);
1342 1382
      _edge_maps.swap(other._edge_maps);
1343 1383
      _attributes.swap(other._attributes);
1344 1384

	
1345 1385
      _nodes_caption = other._nodes_caption;
1346 1386
      _edges_caption = other._edges_caption;
1347 1387
      _attributes_caption = other._attributes_caption;
1348 1388

	
1349 1389
      _sections.swap(other._sections);
1350 1390
    }
1351 1391

	
1352 1392
    /// \brief Destructor
1353 1393
    ~GraphReader() {
1354 1394
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1355 1395
	   it != _node_maps.end(); ++it) {
1356 1396
	delete it->second;
1357 1397
      }
1358 1398

	
1359 1399
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1360 1400
	   it != _edge_maps.end(); ++it) {
1361 1401
	delete it->second;
1362 1402
      }
1363 1403

	
1364 1404
      for (typename Attributes::iterator it = _attributes.begin(); 
1365 1405
	   it != _attributes.end(); ++it) {
1366 1406
	delete it->second;
1367 1407
      }
1368 1408

	
1369 1409
      for (typename Sections::iterator it = _sections.begin(); 
1370 1410
	   it != _sections.end(); ++it) {
1371 1411
	delete it->second;
1372 1412
      }
1373 1413

	
1374 1414
      if (local_is) {
1375 1415
	delete _is;
1376 1416
      }
1377 1417

	
1378 1418
    }
1379 1419

	
1380 1420
  private:
1381 1421
    
1382 1422
    GraphReader& operator=(const GraphReader&);
1383 1423

	
1384 1424
  public:
1385 1425

	
1386 1426
    /// \name Reading rules
1387 1427
    /// @{
1388 1428
    
1389 1429
    /// \brief Node map reading rule
1390 1430
    ///
1391 1431
    /// Add a node map reading rule to the reader.
1392 1432
    template <typename Map>
1393 1433
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1394 1434
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1395 1435
      _reader_bits::MapStorageBase<Node>* storage = 
1396 1436
	new _reader_bits::MapStorage<Node, Map>(map);
1397 1437
      _node_maps.push_back(std::make_pair(caption, storage));
1398 1438
      return *this;
1399 1439
    }
1400 1440

	
1401 1441
    /// \brief Node map reading rule
1402 1442
    ///
1403 1443
    /// Add a node map reading rule with specialized converter to the
1404 1444
    /// reader.
1405 1445
    template <typename Map, typename Converter>
1406 1446
    GraphReader& nodeMap(const std::string& caption, Map& map, 
1407 1447
			   const Converter& converter = Converter()) {
1408 1448
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1409 1449
      _reader_bits::MapStorageBase<Node>* storage = 
1410 1450
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1411 1451
      _node_maps.push_back(std::make_pair(caption, storage));
1412 1452
      return *this;
1413 1453
    }
1414 1454

	
1415 1455
    /// \brief Edge map reading rule
1416 1456
    ///
1417 1457
    /// Add an edge map reading rule to the reader.
1418 1458
    template <typename Map>
1419 1459
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1420 1460
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1421 1461
      _reader_bits::MapStorageBase<Edge>* storage = 
1422 1462
	new _reader_bits::MapStorage<Edge, Map>(map);
1423 1463
      _edge_maps.push_back(std::make_pair(caption, storage));
1424 1464
      return *this;
1425 1465
    }
1426 1466

	
1427 1467
    /// \brief Edge map reading rule
1428 1468
    ///
1429 1469
    /// Add an edge map reading rule with specialized converter to the
1430 1470
    /// reader.
1431 1471
    template <typename Map, typename Converter>
1432 1472
    GraphReader& edgeMap(const std::string& caption, Map& map, 
1433 1473
			  const Converter& converter = Converter()) {
1434 1474
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1435 1475
      _reader_bits::MapStorageBase<Edge>* storage = 
1436 1476
	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1437 1477
      _edge_maps.push_back(std::make_pair(caption, storage));
1438 1478
      return *this;
1439 1479
    }
1440 1480

	
1441 1481
    /// \brief Arc map reading rule
1442 1482
    ///
1443 1483
    /// Add an arc map reading rule to the reader.
1444 1484
    template <typename Map>
1445 1485
    GraphReader& arcMap(const std::string& caption, Map& map) {
1446 1486
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1447 1487
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1448 1488
	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1449 1489
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1450 1490
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1451 1491
	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1452 1492
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1453 1493
      return *this;
1454 1494
    }
1455 1495

	
1456 1496
    /// \brief Arc map reading rule
1457 1497
    ///
1458 1498
    /// Add an arc map reading rule with specialized converter to the
1459 1499
    /// reader.
1460 1500
    template <typename Map, typename Converter>
1461 1501
    GraphReader& arcMap(const std::string& caption, Map& map, 
1462 1502
			  const Converter& converter = Converter()) {
1463 1503
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1464 1504
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1465 1505
	new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1466 1506
	(_graph, map, converter);
1467 1507
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1468 1508
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1469 1509
	new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1470 1510
	(_graph, map, converter);
1471 1511
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1472 1512
      return *this;
1473 1513
    }
1474 1514

	
1475 1515
    /// \brief Attribute reading rule
1476 1516
    ///
1477 1517
    /// Add an attribute reading rule to the reader.
1478 1518
    template <typename Value>
1479 1519
    GraphReader& attribute(const std::string& caption, Value& value) {
1480 1520
      _reader_bits::ValueStorageBase* storage = 
1481 1521
	new _reader_bits::ValueStorage<Value>(value);
1482 1522
      _attributes.insert(std::make_pair(caption, storage));
1483 1523
      return *this;
1484 1524
    }
1485 1525

	
1486 1526
    /// \brief Attribute reading rule
1487 1527
    ///
1488 1528
    /// Add an attribute reading rule with specialized converter to the
1489 1529
    /// reader.
1490 1530
    template <typename Value, typename Converter>
1491 1531
    GraphReader& attribute(const std::string& caption, Value& value, 
1492 1532
			     const Converter& converter = Converter()) {
1493 1533
      _reader_bits::ValueStorageBase* storage = 
1494 1534
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1495 1535
      _attributes.insert(std::make_pair(caption, storage));
1496 1536
      return *this;
1497 1537
    }
1498 1538

	
1499 1539
    /// \brief Node reading rule
1500 1540
    ///
1501 1541
    /// Add a node reading rule to reader.
1502 1542
    GraphReader& node(const std::string& caption, Node& node) {
1503 1543
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1504 1544
      Converter converter(_node_index);
1505 1545
      _reader_bits::ValueStorageBase* storage = 
1506 1546
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1507 1547
      _attributes.insert(std::make_pair(caption, storage));
1508 1548
      return *this;
1509 1549
    }
1510 1550

	
1511 1551
    /// \brief Edge reading rule
1512 1552
    ///
1513 1553
    /// Add an edge reading rule to reader.
1514 1554
    GraphReader& edge(const std::string& caption, Edge& edge) {
1515 1555
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1516 1556
      Converter converter(_edge_index);
1517 1557
      _reader_bits::ValueStorageBase* storage = 
1518 1558
	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1519 1559
      _attributes.insert(std::make_pair(caption, storage));
1520 1560
      return *this;
1521 1561
    }
1522 1562

	
1523 1563
    /// \brief Arc reading rule
1524 1564
    ///
1525 1565
    /// Add an arc reading rule to reader.
1526 1566
    GraphReader& arc(const std::string& caption, Arc& arc) {
1527 1567
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1528 1568
      Converter converter(_graph, _edge_index);
1529 1569
      _reader_bits::ValueStorageBase* storage = 
1530 1570
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1531 1571
      _attributes.insert(std::make_pair(caption, storage));
1532 1572
      return *this;
1533 1573
    }
1534 1574

	
1535 1575
    /// @}
1536 1576

	
1537 1577
    /// \name Select section by name
1538 1578
    /// @{
1539 1579

	
1540 1580
    /// \brief Set \c \@nodes section to be read
1541 1581
    ///
1542 1582
    /// Set \c \@nodes section to be read
1543 1583
    GraphReader& nodes(const std::string& caption) {
1544 1584
      _nodes_caption = caption;
1545 1585
      return *this;
1546 1586
    }
1547 1587

	
1548 1588
    /// \brief Set \c \@edges section to be read
1549 1589
    ///
1550 1590
    /// Set \c \@edges section to be read
1551 1591
    GraphReader& edges(const std::string& caption) {
1552 1592
      _edges_caption = caption;
1553 1593
      return *this;
1554 1594
    }
1555 1595

	
1556 1596
    /// \brief Set \c \@attributes section to be read
1557 1597
    ///
1558 1598
    /// Set \c \@attributes section to be read
1559 1599
    GraphReader& attributes(const std::string& caption) {
1560 1600
      _attributes_caption = caption;
1561 1601
      return *this;
1562 1602
    }
1563 1603

	
1564 1604
    /// @}
1565 1605

	
1566 1606
    /// \name Section readers
1567 1607
    /// @{
1568 1608

	
1569 1609
    /// \brief Add a section processor with line oriented reading
1570 1610
    ///
1571 1611
    /// In the \e LGF file extra sections can be placed, which contain
1572 1612
    /// any data in arbitrary format. These sections can be read with
1573 1613
    /// this function line by line. The first parameter is the type
1574 1614
    /// descriptor of the section, the second is a functor, which
1575 1615
    /// takes just one \c std::string parameter. At the reading
1576 1616
    /// process, each line of the section will be given to the functor
1577 1617
    /// object. However, the empty lines and the comment lines are
1578 1618
    /// filtered out, and the leading whitespaces are stipped from
1579 1619
    /// each processed string.
1580 1620
    ///
1581 1621
    /// For example let's see a section, which contain several
1582 1622
    /// integers, which should be inserted into a vector.
1583 1623
    ///\code
1584 1624
    ///  @numbers
1585 1625
    ///  12 45 23
1586 1626
    ///  4
1587 1627
    ///  23 6
1588 1628
    ///\endcode
1589 1629
    ///
1590 1630
    /// The functor is implemented as an struct:
1591 1631
    ///\code
1592 1632
    ///  struct NumberSection {
1593 1633
    ///    std::vector<int>& _data;
1594 1634
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
1595 1635
    ///    void operator()(const std::string& line) {
1596 1636
    ///      std::istringstream ls(line);
1597 1637
    ///      int value;
1598 1638
    ///      while (ls >> value) _data.push_back(value);
1599 1639
    ///    }
1600 1640
    ///  };
1601 1641
    ///
1602 1642
    ///  // ...
1603 1643
    ///
1604 1644
    ///  reader.sectionLines("numbers", NumberSection(vec));  
1605 1645
    ///\endcode
1606 1646
    template <typename Functor>
1607 1647
    GraphReader& sectionLines(const std::string& type, Functor functor) {
1608 1648
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1609 1649
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1610 1650
		   "Multiple reading of section.");
1611 1651
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1612 1652
		   type != "attributes", "Multiple reading of section.");
1613 1653
      _sections.insert(std::make_pair(type, 
1614 1654
        new _reader_bits::LineSection<Functor>(functor)));
1615 1655
      return *this;
1616 1656
    }
1617 1657

	
1618 1658

	
1619 1659
    /// \brief Add a section processor with stream oriented reading
1620 1660
    ///
1621 1661
    /// In the \e LGF file extra sections can be placed, which contain
1622 1662
    /// any data in arbitrary format. These sections can be read
1623 1663
    /// directly with this function. The first parameter is the type
1624 1664
    /// of the section, the second is a functor, which takes an \c
1625 1665
    /// std::istream& and an int& parameter, the latter regard to the
1626 1666
    /// line number of stream. The functor can read the input while
1627 1667
    /// the section go on, and the line number should be modified
1628 1668
    /// accordingly.
1629 1669
    template <typename Functor>
1630 1670
    GraphReader& sectionStream(const std::string& type, Functor functor) {
1631 1671
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1632 1672
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1633 1673
		   "Multiple reading of section.");
1634 1674
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1635 1675
		   type != "attributes", "Multiple reading of section.");
1636 1676
      _sections.insert(std::make_pair(type, 
1637 1677
	 new _reader_bits::StreamSection<Functor>(functor)));
1638 1678
      return *this;
1639 1679
    }    
1640 1680
    
1641 1681
    /// @}
1642 1682

	
1643 1683
    /// \name Using previously constructed node or edge set
1644 1684
    /// @{
1645 1685

	
1646 1686
    /// \brief Use previously constructed node set
1647 1687
    ///
1648 1688
    /// Use previously constructed node set, and specify the node
1649 1689
    /// label map.
1650 1690
    template <typename Map>
1651 1691
    GraphReader& useNodes(const Map& map) {
1652 1692
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1653 1693
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1654 1694
      _use_nodes = true;
1655 1695
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1656 1696
      for (NodeIt n(_graph); n != INVALID; ++n) {
1657 1697
	_node_index.insert(std::make_pair(converter(map[n]), n));
1658 1698
      }
1659 1699
      return *this;
1660 1700
    }
1661 1701

	
1662 1702
    /// \brief Use previously constructed node set
1663 1703
    ///
1664 1704
    /// Use previously constructed node set, and specify the node
1665 1705
    /// label map and a functor which converts the label map values to
1666 1706
    /// std::string.
1667 1707
    template <typename Map, typename Converter>
1668 1708
    GraphReader& useNodes(const Map& map, 
1669 1709
			    const Converter& converter = Converter()) {
1670 1710
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1671 1711
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1672 1712
      _use_nodes = true;
1673 1713
      for (NodeIt n(_graph); n != INVALID; ++n) {
1674 1714
	_node_index.insert(std::make_pair(converter(map[n]), n));
1675 1715
      }
1676 1716
      return *this;
1677 1717
    }
1678 1718

	
1679 1719
    /// \brief Use previously constructed edge set
1680 1720
    ///
1681 1721
    /// Use previously constructed edge set, and specify the edge
1682 1722
    /// label map.
1683 1723
    template <typename Map>
1684 1724
    GraphReader& useEdges(const Map& map) {
1685 1725
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1686 1726
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1687 1727
      _use_edges = true;
1688 1728
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1689 1729
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1690 1730
	_edge_index.insert(std::make_pair(converter(map[a]), a));
1691 1731
      }
1692 1732
      return *this;
1693 1733
    }
1694 1734

	
1695 1735
    /// \brief Use previously constructed edge set
1696 1736
    ///
1697 1737
    /// Use previously constructed edge set, and specify the edge
1698 1738
    /// label map and a functor which converts the label map values to
1699 1739
    /// std::string.
1700 1740
    template <typename Map, typename Converter>
1701 1741
    GraphReader& useEdges(const Map& map, 
1702 1742
			    const Converter& converter = Converter()) {
1703 1743
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1704 1744
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); 
1705 1745
      _use_edges = true;
1706 1746
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1707 1747
	_edge_index.insert(std::make_pair(converter(map[a]), a));
1708 1748
      }
1709 1749
      return *this;
1710 1750
    }
1711 1751

	
1752
    /// \brief Skips the reading of node section
1753
    ///
1754
    /// Omit the reading of the node section. This implies that each node
1755
    /// map reading rule will be abanoned, and the nodes of the graph
1756
    /// will not be constructed, which usually cause that the edge set
1757
    /// could not be read due to lack of node name
1758
    /// resolving. Therefore, the \c skipEdges() should be used too, or
1759
    /// the useNodes() member function should be used to specify the
1760
    /// label of the nodes.
1761
    GraphReader& skipNodes() {
1762
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
1763
      _skip_nodes = true;
1764
      return *this;
1765
    }
1766

	
1767
    /// \brief Skips the reading of edge section
1768
    ///
1769
    /// Omit the reading of the edge section. This implies that each edge
1770
    /// map reading rule will be abanoned, and the edges of the graph
1771
    /// will not be constructed.
1772
    GraphReader& skipEdges() {
1773
      LEMON_ASSERT(!_skip_edges, "Skip edges already set"); 
1774
      _skip_edges = true;
1775
      return *this;
1776
    }
1777

	
1712 1778
    /// @}
1713 1779

	
1714 1780
  private:
1715 1781

	
1716 1782
    bool readLine() {
1717 1783
      std::string str;
1718 1784
      while(++line_num, std::getline(*_is, str)) {
1719 1785
	line.clear(); line.str(str);
1720 1786
	char c;
1721 1787
	if (line >> std::ws >> c && c != '#') {
1722 1788
	  line.putback(c);
1723 1789
	  return true;
1724 1790
	}
1725 1791
      }
1726 1792
      return false;
1727 1793
    }
1728 1794

	
1729 1795
    bool readSuccess() {
1730 1796
      return static_cast<bool>(*_is);
1731 1797
    }
1732 1798
    
1733 1799
    void skipSection() {
1734 1800
      char c;
1735 1801
      while (readSuccess() && line >> c && c != '@') {
1736 1802
	readLine();
1737 1803
      }
1738 1804
      line.putback(c);
1739 1805
    }
1740 1806

	
1741 1807
    void readNodes() {
1742 1808

	
1743 1809
      std::vector<int> map_index(_node_maps.size());
1744 1810
      int map_num, label_index;
1745 1811

	
1746 1812
      char c;
1747 1813
      if (!readLine() || !(line >> c) || c == '@') {
1748 1814
	if (readSuccess() && line) line.putback(c);
1749 1815
	if (!_node_maps.empty()) 
1750 1816
	  throw DataFormatError("Cannot find map names");
1751 1817
	return;
1752 1818
      }
1753 1819
      line.putback(c);
1754 1820
      
1755 1821
      {
1756 1822
	std::map<std::string, int> maps;
1757 1823
	
1758 1824
	std::string map;
1759 1825
	int index = 0;
1760 1826
	while (_reader_bits::readToken(line, map)) {
1761 1827
	  if (maps.find(map) != maps.end()) {
1762 1828
	    std::ostringstream msg;
1763 1829
	    msg << "Multiple occurence of node map: " << map;
1764 1830
	    throw DataFormatError(msg.str().c_str());
1765 1831
	  }
1766 1832
	  maps.insert(std::make_pair(map, index));
1767 1833
	  ++index;
1768 1834
	}
1769 1835
	
1770 1836
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1771 1837
	  std::map<std::string, int>::iterator jt = 
1772 1838
	    maps.find(_node_maps[i].first);
1773 1839
	  if (jt == maps.end()) {
1774 1840
	    std::ostringstream msg;
1775 1841
	    msg << "Map not found in file: " << _node_maps[i].first;
1776 1842
	    throw DataFormatError(msg.str().c_str());
1777 1843
	  }
1778 1844
	  map_index[i] = jt->second;
1779 1845
	}
1780 1846

	
1781 1847
	{
1782 1848
	  std::map<std::string, int>::iterator jt = maps.find("label");
1783 1849
	  if (jt != maps.end()) {
1784 1850
	    label_index = jt->second;
1785 1851
	  } else {
1786 1852
	    label_index = -1;
1787 1853
	  }
1788 1854
	}
1789 1855
	map_num = maps.size();
1790 1856
      }
1791 1857

	
1792 1858
      while (readLine() && line >> c && c != '@') {
1793 1859
	line.putback(c);
1794 1860

	
1795 1861
	std::vector<std::string> tokens(map_num);
1796 1862
	for (int i = 0; i < map_num; ++i) {
1797 1863
	  if (!_reader_bits::readToken(line, tokens[i])) {
1798 1864
	    std::ostringstream msg;
1799 1865
	    msg << "Column not found (" << i + 1 << ")";
1800 1866
	    throw DataFormatError(msg.str().c_str());
1801 1867
	  }
1802 1868
	}
1803 1869
	if (line >> std::ws >> c)
1804 1870
	  throw DataFormatError("Extra character on the end of line");
1805 1871
	
1806 1872
	Node n;
1807 1873
	if (!_use_nodes) {
1808 1874
	  n = _graph.addNode();
1809 1875
	  if (label_index != -1) 
1810 1876
	    _node_index.insert(std::make_pair(tokens[label_index], n));
1811 1877
	} else {
1812 1878
	  if (label_index == -1) 
1813 1879
	    throw DataFormatError("Label map not found in file");
1814 1880
	  typename std::map<std::string, Node>::iterator it =
1815 1881
	    _node_index.find(tokens[label_index]);
1816 1882
	  if (it == _node_index.end()) {
1817 1883
	    std::ostringstream msg;
1818 1884
	    msg << "Node with label not found: " << tokens[label_index];
1819 1885
	    throw DataFormatError(msg.str().c_str());	    
1820 1886
	  }
1821 1887
	  n = it->second;
1822 1888
	}
1823 1889

	
1824 1890
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1825 1891
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
1826 1892
	}
1827 1893

	
1828 1894
      }
1829 1895
      if (readSuccess()) {
1830 1896
	line.putback(c);
1831 1897
      }
1832 1898
    }
1833 1899

	
1834 1900
    void readEdges() {
1835 1901

	
1836 1902
      std::vector<int> map_index(_edge_maps.size());
1837 1903
      int map_num, label_index;
1838 1904

	
1839 1905
      char c;
1840 1906
      if (!readLine() || !(line >> c) || c == '@') {
1841 1907
	if (readSuccess() && line) line.putback(c);
1842 1908
	if (!_edge_maps.empty()) 
1843 1909
	  throw DataFormatError("Cannot find map names");
1844 1910
	return;
1845 1911
      }
1846 1912
      line.putback(c);
1847 1913
      
1848 1914
      {
1849 1915
	std::map<std::string, int> maps;
1850 1916
	
1851 1917
	std::string map;
1852 1918
	int index = 0;
1853 1919
	while (_reader_bits::readToken(line, map)) {
1854 1920
	  if (maps.find(map) != maps.end()) {
1855 1921
	    std::ostringstream msg;
1856 1922
	    msg << "Multiple occurence of edge map: " << map;
1857 1923
	    throw DataFormatError(msg.str().c_str());
1858 1924
	  }
1859 1925
	  maps.insert(std::make_pair(map, index));
1860 1926
	  ++index;
1861 1927
	}
1862 1928
	
1863 1929
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1864 1930
	  std::map<std::string, int>::iterator jt = 
1865 1931
	    maps.find(_edge_maps[i].first);
1866 1932
	  if (jt == maps.end()) {
1867 1933
	    std::ostringstream msg;
1868 1934
	    msg << "Map not found in file: " << _edge_maps[i].first;
1869 1935
	    throw DataFormatError(msg.str().c_str());
1870 1936
	  }
1871 1937
	  map_index[i] = jt->second;
1872 1938
	}
1873 1939

	
1874 1940
	{
1875 1941
	  std::map<std::string, int>::iterator jt = maps.find("label");
1876 1942
	  if (jt != maps.end()) {
1877 1943
	    label_index = jt->second;
1878 1944
	  } else {
1879 1945
	    label_index = -1;
1880 1946
	  }
1881 1947
	}
1882 1948
	map_num = maps.size();
1883 1949
      }
1884 1950

	
1885 1951
      while (readLine() && line >> c && c != '@') {
1886 1952
	line.putback(c);
1887 1953

	
1888 1954
	std::string source_token;
1889 1955
	std::string target_token;
1890 1956

	
1891 1957
	if (!_reader_bits::readToken(line, source_token))
1892 1958
	  throw DataFormatError("Node u not found");
1893 1959

	
1894 1960
	if (!_reader_bits::readToken(line, target_token))
1895 1961
	  throw DataFormatError("Node v not found");
1896 1962
	
1897 1963
	std::vector<std::string> tokens(map_num);
1898 1964
	for (int i = 0; i < map_num; ++i) {
1899 1965
	  if (!_reader_bits::readToken(line, tokens[i])) {
1900 1966
	    std::ostringstream msg;
1901 1967
	    msg << "Column not found (" << i + 1 << ")";
1902 1968
	    throw DataFormatError(msg.str().c_str());
1903 1969
	  }
1904 1970
	}
1905 1971
	if (line >> std::ws >> c)
1906 1972
	  throw DataFormatError("Extra character on the end of line");
1907 1973
	
1908 1974
	Edge e;
1909 1975
	if (!_use_edges) {
1910 1976

	
1911 1977
          typename NodeIndex::iterator it;
1912 1978
 
1913 1979
          it = _node_index.find(source_token);
1914 1980
          if (it == _node_index.end()) {
1915 1981
            std::ostringstream msg;
1916 1982
            msg << "Item not found: " << source_token;
1917 1983
            throw DataFormatError(msg.str().c_str());
1918 1984
          }
1919 1985
          Node source = it->second;
1920 1986

	
1921 1987
          it = _node_index.find(target_token);
1922 1988
          if (it == _node_index.end()) {       
1923 1989
            std::ostringstream msg;            
1924 1990
            msg << "Item not found: " << target_token;
1925 1991
            throw DataFormatError(msg.str().c_str());
1926 1992
          }                                          
1927 1993
          Node target = it->second;                            
1928 1994

	
1929 1995
	  e = _graph.addEdge(source, target);
1930 1996
	  if (label_index != -1) 
1931 1997
	    _edge_index.insert(std::make_pair(tokens[label_index], e));
1932 1998
	} else {
1933 1999
	  if (label_index == -1) 
1934 2000
	    throw DataFormatError("Label map not found in file");
1935 2001
	  typename std::map<std::string, Edge>::iterator it =
1936 2002
	    _edge_index.find(tokens[label_index]);
1937 2003
	  if (it == _edge_index.end()) {
1938 2004
	    std::ostringstream msg;
1939 2005
	    msg << "Edge with label not found: " << tokens[label_index];
1940 2006
	    throw DataFormatError(msg.str().c_str());	    
1941 2007
	  }
1942 2008
	  e = it->second;
1943 2009
	}
1944 2010

	
1945 2011
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1946 2012
	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
1947 2013
	}
1948 2014

	
1949 2015
      }
1950 2016
      if (readSuccess()) {
1951 2017
	line.putback(c);
1952 2018
      }
1953 2019
    }
1954 2020

	
1955 2021
    void readAttributes() {
1956 2022

	
1957 2023
      std::set<std::string> read_attr;
1958 2024

	
1959 2025
      char c;
1960 2026
      while (readLine() && line >> c && c != '@') {
1961 2027
	line.putback(c);
1962 2028
	
1963 2029
	std::string attr, token;
1964 2030
	if (!_reader_bits::readToken(line, attr))
1965 2031
	  throw DataFormatError("Attribute name not found");
1966 2032
	if (!_reader_bits::readToken(line, token))
1967 2033
	  throw DataFormatError("Attribute value not found");
1968 2034
	if (line >> c)
1969 2035
	  throw DataFormatError("Extra character on the end of line");	  
1970 2036

	
1971 2037
	{
1972 2038
	  std::set<std::string>::iterator it = read_attr.find(attr);
1973 2039
	  if (it != read_attr.end()) {
1974 2040
	    std::ostringstream msg;
1975 2041
	    msg << "Multiple occurence of attribute " << attr;
1976 2042
	    throw DataFormatError(msg.str().c_str());
1977 2043
	  }
1978 2044
	  read_attr.insert(attr);
1979 2045
	}
1980 2046
	
1981 2047
	{
1982 2048
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1983 2049
	  while (it != _attributes.end() && it->first == attr) {
1984 2050
	    it->second->set(token);
1985 2051
	    ++it;
1986 2052
	  }
1987 2053
	}
1988 2054

	
1989 2055
      }
1990 2056
      if (readSuccess()) {
1991 2057
	line.putback(c);
1992 2058
      }
1993 2059
      for (typename Attributes::iterator it = _attributes.begin();
1994 2060
	   it != _attributes.end(); ++it) {
1995 2061
	if (read_attr.find(it->first) == read_attr.end()) {
1996 2062
	  std::ostringstream msg;
1997 2063
	  msg << "Attribute not found in file: " << it->first;
1998 2064
	  throw DataFormatError(msg.str().c_str());
1999 2065
	}	
2000 2066
      }
2001 2067
    }
2002 2068

	
2003 2069
  public:
2004 2070

	
2005 2071
    /// \name Execution of the reader    
2006 2072
    /// @{
2007 2073

	
2008 2074
    /// \brief Start the batch processing
2009 2075
    ///
2010 2076
    /// This function starts the batch processing
2011 2077
    void run() {
2012 2078
      
2013 2079
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2014 2080
      
2015
      bool nodes_done = false;
2016
      bool edges_done = false;
2081
      bool nodes_done = _skip_nodes;
2082
      bool edges_done = _skip_edges;
2017 2083
      bool attributes_done = false;
2018 2084
      std::set<std::string> extra_sections;
2019 2085

	
2020 2086
      line_num = 0;      
2021 2087
      readLine();
2022 2088
      skipSection();
2023 2089

	
2024 2090
      while (readSuccess()) {
2025 2091
	try {
2026 2092
	  char c;
2027 2093
	  std::string section, caption;
2028 2094
	  line >> c;
2029 2095
	  _reader_bits::readToken(line, section);
2030 2096
	  _reader_bits::readToken(line, caption);
2031 2097

	
2032 2098
	  if (line >> c) 
2033 2099
	    throw DataFormatError("Extra character on the end of line");
2034 2100

	
2035 2101
	  if (section == "nodes" && !nodes_done) {
2036 2102
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
2037 2103
	      readNodes();
2038 2104
	      nodes_done = true;
2039 2105
	    }
2040 2106
	  } else if ((section == "edges" || section == "arcs") && 
2041 2107
		     !edges_done) {
2042 2108
	    if (_edges_caption.empty() || _edges_caption == caption) {
2043 2109
	      readEdges();
2044 2110
	      edges_done = true;
2045 2111
	    }
2046 2112
	  } else if (section == "attributes" && !attributes_done) {
2047 2113
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
2048 2114
	      readAttributes();
2049 2115
	      attributes_done = true;
2050 2116
	    }
2051 2117
	  } else {
2052 2118
	    if (extra_sections.find(section) != extra_sections.end()) {
2053 2119
	      std::ostringstream msg;
2054 2120
	      msg << "Multiple occurence of section " << section;
2055 2121
	      throw DataFormatError(msg.str().c_str());
2056 2122
	    }
2057 2123
	    Sections::iterator it = _sections.find(section);
2058 2124
	    if (it != _sections.end()) {
2059 2125
	      extra_sections.insert(section);
2060 2126
	      it->second->process(*_is, line_num);
2061 2127
	    }
2062 2128
	    readLine();
2063 2129
	    skipSection();
2064 2130
	  }
2065 2131
	} catch (DataFormatError& error) {
2066 2132
	  error.line(line_num);
2067 2133
	  throw;
2068 2134
	}	
2069 2135
      }
2070 2136

	
2071 2137
      if (!nodes_done) {
2072 2138
	throw DataFormatError("Section @nodes not found");
2073 2139
      }
2074 2140

	
2075 2141
      if (!edges_done) {
2076 2142
	throw DataFormatError("Section @edges not found");
2077 2143
      }
2078 2144

	
2079 2145
      if (!attributes_done && !_attributes.empty()) {
2080 2146
	throw DataFormatError("Section @attributes not found");
2081 2147
      }
2082 2148

	
2083 2149
    }
2084 2150

	
2085 2151
    /// @}
2086 2152
    
2087 2153
  };
2088 2154

	
2089 2155
  /// \relates GraphReader
2090 2156
  template <typename Graph>
2091 2157
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
2092 2158
    GraphReader<Graph> tmp(is, graph);
2093 2159
    return tmp;
2094 2160
  }
2095 2161

	
2096 2162
  /// \relates GraphReader
2097 2163
  template <typename Graph>
2098 2164
  GraphReader<Graph> graphReader(const std::string& fn, 
2099 2165
				       Graph& graph) {
2100 2166
    GraphReader<Graph> tmp(fn, graph);
2101 2167
    return tmp;
2102 2168
  }
2103 2169

	
2104 2170
  /// \relates GraphReader
2105 2171
  template <typename Graph>
2106 2172
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
2107 2173
    GraphReader<Graph> tmp(fn, graph);
2108 2174
    return tmp;
2109 2175
  }
2110 2176

	
2111 2177
  /// \ingroup lemon_io
2112 2178
  ///
2113 2179
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
2114 2180
  ///
2115 2181
  /// This class can be used to read the sections, the map names and
2116 2182
  /// the attributes from a file. Usually, the Lemon programs know
2117 2183
  /// that, which type of graph, which maps and which attributes
2118 2184
  /// should be read from a file, but in general tools (like glemon)
2119 2185
  /// the contents of an LGF file should be guessed somehow. This class
2120 2186
  /// reads the graph and stores the appropriate information for
2121 2187
  /// reading the graph.
2122 2188
  ///
2123 2189
  ///\code LgfContents contents("graph.lgf"); 
2124 2190
  /// contents.run();
2125 2191
  ///
2126 2192
  /// // does it contain any node section and arc section
2127 2193
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2128 2194
  ///   std::cerr << "Failure, cannot find graph" << std::endl;
2129 2195
  ///   return -1;
2130 2196
  /// }
2131 2197
  /// std::cout << "The name of the default node section : " 
2132 2198
  ///           << contents.nodeSection(0) << std::endl;
2133 2199
  /// std::cout << "The number of the arc maps : " 
2134 2200
  ///           << contents.arcMaps(0).size() << std::endl;
2135 2201
  /// std::cout << "The name of second arc map : " 
2136 2202
  ///           << contents.arcMaps(0)[1] << std::endl;
2137 2203
  ///\endcode
2138 2204
  class LgfContents {    
2139 2205
  private:
2140 2206

	
2141 2207
    std::istream* _is;
2142 2208
    bool local_is;
2143 2209

	
2144 2210
    std::vector<std::string> _node_sections;
2145 2211
    std::vector<std::string> _edge_sections;
2146 2212
    std::vector<std::string> _attribute_sections;
2147 2213
    std::vector<std::string> _extra_sections;
2148 2214

	
2149 2215
    std::vector<bool> _arc_sections;
2150 2216

	
2151 2217
    std::vector<std::vector<std::string> > _node_maps;
2152 2218
    std::vector<std::vector<std::string> > _edge_maps;
2153 2219

	
2154 2220
    std::vector<std::vector<std::string> > _attributes;
2155 2221

	
2156 2222

	
2157 2223
    int line_num;
2158 2224
    std::istringstream line;
2159 2225
    
2160 2226
  public:
2161 2227

	
2162 2228
    /// \brief Constructor
2163 2229
    ///
2164 2230
    /// Construct an \e LGF contents reader, which reads from the given
2165 2231
    /// input stream.
2166 2232
    LgfContents(std::istream& is) 
2167 2233
      : _is(&is), local_is(false) {}
2168 2234

	
2169 2235
    /// \brief Constructor
2170 2236
    ///
2171 2237
    /// Construct an \e LGF contents reader, which reads from the given
2172 2238
    /// file.
2173 2239
    LgfContents(const std::string& fn) 
2174 2240
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2175 2241

	
2176 2242
    /// \brief Constructor
2177 2243
    ///
2178 2244
    /// Construct an \e LGF contents reader, which reads from the given
2179 2245
    /// file.
2180 2246
    LgfContents(const char* fn)
2181 2247
      : _is(new std::ifstream(fn)), local_is(true) {}
2182 2248

	
2183 2249
    /// \brief Copy constructor
2184 2250
    ///
2185 2251
    /// The copy constructor transfers all data from the other reader,
2186 2252
    /// therefore the copied reader will not be usable more. 
2187 2253
    LgfContents(LgfContents& other)
2188 2254
      : _is(other._is), local_is(other.local_is) {
2189 2255
      
2190 2256
      other._is = 0;
2191 2257
      other.local_is = false;
2192 2258
      
2193 2259
      _node_sections.swap(other._node_sections);
2194 2260
      _edge_sections.swap(other._edge_sections);
2195 2261
      _attribute_sections.swap(other._attribute_sections);
2196 2262
      _extra_sections.swap(other._extra_sections);
2197 2263

	
2198 2264
      _arc_sections.swap(other._arc_sections);
2199 2265

	
2200 2266
      _node_maps.swap(other._node_maps);
2201 2267
      _edge_maps.swap(other._edge_maps);
2202 2268
      _attributes.swap(other._attributes);
2203 2269
    }
2204 2270
    
2205 2271
    /// \brief Destructor
2206 2272
    ~LgfContents() {
2207 2273
      if (local_is) delete _is;
2208 2274
    }
2209 2275

	
2210 2276

	
2211 2277
    /// \name Node sections
2212 2278
    /// @{
2213 2279

	
2214 2280
    /// \brief Gives back the number of node sections in the file.
2215 2281
    ///
2216 2282
    /// Gives back the number of node sections in the file.
2217 2283
    int nodeSectionNum() const {
2218 2284
      return _node_sections.size();
2219 2285
    }
2220 2286

	
2221 2287
    /// \brief Returns the section name at the given position. 
2222 2288
    ///
2223 2289
    /// Returns the section name at the given position. 
2224 2290
    const std::string& nodeSection(int i) const {
2225 2291
      return _node_sections[i];
2226 2292
    }
2227 2293

	
2228 2294
    /// \brief Gives back the node maps for the given section.
2229 2295
    ///
2230 2296
    /// Gives back the node maps for the given section.
2231 2297
    const std::vector<std::string>& nodeMapNames(int i) const {
2232 2298
      return _node_maps[i];
2233 2299
    }
2234 2300

	
2235 2301
    /// @}
2236 2302

	
2237 2303
    /// \name Arc/Edge sections 
2238 2304
    /// @{
2239 2305

	
2240 2306
    /// \brief Gives back the number of arc/edge sections in the file.
2241 2307
    ///
2242 2308
    /// Gives back the number of arc/edge sections in the file.
2243 2309
    /// \note It is synonym of \c edgeSectionNum().
2244 2310
    int arcSectionNum() const {
2245 2311
      return _edge_sections.size();
2246 2312
    }
2247 2313

	
2248 2314
    /// \brief Returns the section name at the given position. 
2249 2315
    ///
2250 2316
    /// Returns the section name at the given position. 
2251 2317
    /// \note It is synonym of \c edgeSection().
2252 2318
    const std::string& arcSection(int i) const {
2253 2319
      return _edge_sections[i];
2254 2320
    }
2255 2321

	
2256 2322
    /// \brief Gives back the arc/edge maps for the given section.
2257 2323
    ///
2258 2324
    /// Gives back the arc/edge maps for the given section.
2259 2325
    /// \note It is synonym of \c edgeMapNames().
2260 2326
    const std::vector<std::string>& arcMapNames(int i) const {
2261 2327
      return _edge_maps[i];
2262 2328
    }
2263 2329

	
2264 2330
    /// @}
2265 2331

	
2266 2332
    /// \name Synonyms
2267 2333
    /// @{
2268 2334

	
2269 2335
    /// \brief Gives back the number of arc/edge sections in the file.
2270 2336
    ///
2271 2337
    /// Gives back the number of arc/edge sections in the file.
2272 2338
    /// \note It is synonym of \c arcSectionNum().
2273 2339
    int edgeSectionNum() const {
2274 2340
      return _edge_sections.size();
2275 2341
    }
2276 2342

	
2277 2343
    /// \brief Returns the section name at the given position. 
2278 2344
    ///
2279 2345
    /// Returns the section name at the given position. 
2280 2346
    /// \note It is synonym of \c arcSection().
2281 2347
    const std::string& edgeSection(int i) const {
2282 2348
      return _edge_sections[i];
2283 2349
    }
2284 2350

	
2285 2351
    /// \brief Gives back the edge maps for the given section.
2286 2352
    ///
2287 2353
    /// Gives back the edge maps for the given section.
2288 2354
    /// \note It is synonym of \c arcMapNames().
2289 2355
    const std::vector<std::string>& edgeMapNames(int i) const {
2290 2356
      return _edge_maps[i];
2291 2357
    }
2292 2358

	
2293 2359
    /// @}
2294 2360

	
2295 2361
    /// \name Attribute sections   
2296 2362
    /// @{
2297 2363

	
2298 2364
    /// \brief Gives back the number of attribute sections in the file.
2299 2365
    ///
2300 2366
    /// Gives back the number of attribute sections in the file.
2301 2367
    int attributeSectionNum() const {
2302 2368
      return _attribute_sections.size();
2303 2369
    }
2304 2370

	
2305 2371
    /// \brief Returns the section name at the given position. 
2306 2372
    ///
2307 2373
    /// Returns the section name at the given position. 
2308 2374
    const std::string& attributeSectionNames(int i) const {
2309 2375
      return _attribute_sections[i];
2310 2376
    }
2311 2377

	
2312 2378
    /// \brief Gives back the attributes for the given section.
2313 2379
    ///
2314 2380
    /// Gives back the attributes for the given section.
2315 2381
    const std::vector<std::string>& attributes(int i) const {
2316 2382
      return _attributes[i];
2317 2383
    }
2318 2384

	
2319 2385
    /// @}
2320 2386

	
2321 2387
    /// \name Extra sections   
2322 2388
    /// @{
2323 2389

	
2324 2390
    /// \brief Gives back the number of extra sections in the file.
2325 2391
    ///
2326 2392
    /// Gives back the number of extra sections in the file.
2327 2393
    int extraSectionNum() const {
2328 2394
      return _extra_sections.size();
2329 2395
    }
2330 2396

	
2331 2397
    /// \brief Returns the extra section type at the given position. 
2332 2398
    ///
2333 2399
    /// Returns the section type at the given position. 
2334 2400
    const std::string& extraSection(int i) const {
2335 2401
      return _extra_sections[i];
2336 2402
    }
2337 2403

	
2338 2404
    /// @}
2339 2405

	
2340 2406
  private:
2341 2407

	
2342 2408
    bool readLine() {
2343 2409
      std::string str;
2344 2410
      while(++line_num, std::getline(*_is, str)) {
2345 2411
	line.clear(); line.str(str);
2346 2412
	char c;
2347 2413
	if (line >> std::ws >> c && c != '#') {
2348 2414
	  line.putback(c);
2349 2415
	  return true;
2350 2416
	}
2351 2417
      }
2352 2418
      return false;
2353 2419
    }
2354 2420

	
2355 2421
    bool readSuccess() {
2356 2422
      return static_cast<bool>(*_is);
2357 2423
    }
2358 2424

	
2359 2425
    void skipSection() {
2360 2426
      char c;
2361 2427
      while (readSuccess() && line >> c && c != '@') {
2362 2428
	readLine();
2363 2429
      }
2364 2430
      line.putback(c);
2365 2431
    }
2366 2432

	
2367 2433
    void readMaps(std::vector<std::string>& maps) {
2368 2434
      char c;
2369 2435
      if (!readLine() || !(line >> c) || c == '@') {
2370 2436
	if (readSuccess() && line) line.putback(c);
2371 2437
	return;
2372 2438
      }
2373 2439
      line.putback(c);
2374 2440
      std::string map;
2375 2441
      while (_reader_bits::readToken(line, map)) {
2376 2442
	maps.push_back(map);
2377 2443
      }
2378 2444
    }
2379 2445

	
2380 2446
    void readAttributes(std::vector<std::string>& attrs) {
2381 2447
      readLine();
2382 2448
      char c;
2383 2449
      while (readSuccess() && line >> c && c != '@') {
2384 2450
	line.putback(c);
2385 2451
	std::string attr;
2386 2452
	_reader_bits::readToken(line, attr);
2387 2453
	attrs.push_back(attr);
2388 2454
	readLine();
2389 2455
      }
2390 2456
      line.putback(c);
2391 2457
    }
2392 2458

	
2393 2459
  public:
2394 2460

	
2395 2461
    /// \name Execution of the contents reader    
2396 2462
    /// @{
2397 2463

	
2398 2464
    /// \brief Start the reading
2399 2465
    ///
2400 2466
    /// This function starts the reading
0 comments (0 inline)